--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(wrt-plugin-ivi)
+
+SET(CMAKE_INSTALL_PREFIX "/usr")
+
+# -----------------------------------------------------------------------------
+# Required platform modules
+# -----------------------------------------------------------------------------
+INCLUDE(FindPkgConfig)
+
+PKG_CHECK_MODULES(dpl REQUIRED dpl-efl)
+PKG_CHECK_MODULES(wrt-plugins-types REQUIRED wrt-plugins-types)
+PKG_CHECK_MODULES(wrt-deviceapis-commons-javascript REQUIRED wrt-plugins-commons-javascript)
+PKG_CHECK_MODULES(wrt-plugins-tizen-common REQUIRED wrt-plugins-tizen-common)
+PKG_CHECK_MODULES(json-glib REQUIRED json-glib-1.0)
+
+INCLUDE_DIRECTORIES(
+ ${dpl_INCLUDE_DIRS}
+ ${wrt-plugins-types_INCLUDE_DIRS}
+ ${wrt-deviceapis-commons-javascript_INCLUDE_DIRS}
+ ${wrt-plugins-tizen-common_INCLUDE_DIRS}
+ ${json-glib_INCLUDE_DIRS}
+)
+
+# -----------------------------------------------------------------------------
+# Determine the log option
+# -----------------------------------------------------------------------------
+
+OPTION(DPL_LOG "DPL logs status" ON)
+
+IF(DPL_LOG)
+ MESSAGE(STATUS "Logging enabled for DPL")
+ ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
+ELSE(DPL_LOG)
+ MESSAGE(STATUS "Logging disabled for DPL")
+ENDIF(DPL_LOG)
+
+# -----------------------------------------------------------------------------
+# Determine the time tracing option
+# -----------------------------------------------------------------------------
+
+OPTION(ENABLE_TIME_TRACER "TIME TRACING" OFF)
+
+IF(ENABLE_TIME_TRACER)
+ MESSAGE(STATUS "Time tracer enabled")
+ ADD_DEFINITIONS("-DENABLE_TIME_TRACER")
+ELSE(ENABLE_TIME_TRACER)
+ MESSAGE(STATUS "Time tracer disabled")
+ENDIF(ENABLE_TIME_TRACER)
+
+# -----------------------------------------------------------------------------
+# Set build type (Release by default)
+# -----------------------------------------------------------------------------
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+ SET(CMAKE_BUILD_TYPE Release)
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+# -----------------------------------------------------------------------------
+# CFlags
+# -----------------------------------------------------------------------------
+SET(CMAKE_C_FLAGS_PROFILING "-O0 -g -pg")
+SET(CMAKE_CXX_FLAGS_PROFILING "-O0 -std=c++0x -g -pg")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -std=c++0x -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -std=c++0x -g")
+ADD_DEFINITIONS("-DCLIENT_IPC_THREAD")
+ADD_DEFINITIONS("-DEXPORT_API=")
+ADD_DEFINITIONS("-Wall")
+ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64")
+#ADD_DEFINITIONS("-Werror")
+#ADD_DEFINITIONS("-Wextra")
+ADD_DEFINITIONS("-DAPPLICATION_API_BACKWARD_COMPATIBILITY")
+ADD_DEFINITIONS("-std=c++11")
+
+
+# -----------------------------------------------------------------------------
+# Schema of plugin's configuration file
+# -----------------------------------------------------------------------------
+SET(COMMON_CONFIG_DTD ${CMAKE_CURRENT_SOURCE_DIR}/config.dtd)
+SET(COMMON_CONFIG_DTD_DST /usr/etc/tizen-apis)
+INSTALL(FILES ${COMMON_CONFIG_DTD} DESTINATION ${COMMON_CONFIG_DTD_DST})
+
+# -----------------------------------------------------------------------------
+# Global variables
+# -----------------------------------------------------------------------------
+
+SET(DESTINATION_LIB_PREFIX lib/wrt-plugins)
+
+SET(DESTINATION_HEADER_PREFIX include/${PROJECT_NAME})
+
+SET(LIBS_WIDGETDB ${wrt-plugins-widgetdb_LIBRARIES})
+
+# -----------------------------------------------------------------------------
+# Macros for pkgconfig
+# -----------------------------------------------------------------------------
+SET(PKGCONFIG_DIR ${CMAKE_SOURCE_DIR}/pkgconfigs)
+#SET(PKGCONFIG_DIR ${CMAKE_SOURCE_DIR})
+
+MACRO(configure_and_install_pkg PKG_FILE)
+ CONFIGURE_FILE(${PKGCONFIG_DIR}/${PKG_FILE}.in
+ ${PKGCONFIG_DIR}/${PKG_FILE} @ONLY)
+ INSTALL(FILES ${PKGCONFIG_DIR}/${PKG_FILE} DESTINATION lib/pkgconfig)
+ENDMACRO(configure_and_install_pkg)
+
+SET(TARGET_NAME wrt-plugins-tizen-phone)
+SET(DESTINATION_NAME tizen-phone)
+SET(TARGET_IMPL_NAME wrt-plugins-tizen-phone-impl)
+
+configure_and_install_pkg(wrt-plugins-tizen-phone.pc)
+
+SET(CMAKE_INSTALL_RPATH
+ ${CMAKE_INSTALL_RPATH}
+ ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+ ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+ src/Phone.cpp
+ src/JSPhone.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+ ${dpl_LDFLAGS}
+ ${dpl-event_LDFLAGS}
+ ${wrt-deviceapis-commons-javascript_LDFLAGS}
+ ${wrt-plugins-tizen-common_LDFLAGS}
+ ${json-glib_LDFLAGS}
+ -L/usr/lib/wrt-plugins/tizen-tizen/
+)
+
+SET(SRCS
+ src/plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/ DESTINATION ${DESTINATION_HEADER_PREFIX}/phone
+ FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+
--- /dev/null
+<!ELEMENT plugin-properties (library-name, feature-install-uri?,
+ feature-key-cn?, feature-root-cn?,
+ feature-root-fingerprint?, feature-set*, api-feature+) >
+
+<!ELEMENT library-name (#PCDATA)>
+
+<!ELEMENT feature-set (api-feature-ref+)>
+<!ATTLIST feature-set name CDATA #REQUIRED >
+
+<!ELEMENT api-feature-ref EMPTY>
+<!ATTLIST api-feature-ref name CDATA #REQUIRED >
+
+<!ELEMENT api-feature (name, device-capability*, Object*, Function*, Property* )>
+
+<!ELEMENT name (#PCDATA) >
+<!ELEMENT device-capability (#PCDATA )>
+
+<!ELEMENT Object (Function*, Property*)>
+<!ATTLIST Object name CDATA #REQUIRED >
+
+<!ELEMENT Function (#PCDATA )>
+<!ATTLIST Function name CDATA #REQUIRED >
+<!ATTLIST Function restricted CDATA #IMPLIED >
+
+<!ELEMENT Property (#PCDATA )>
+
+
+<!ELEMENT feature-install-uri (#PCDATA)>
+<!ELEMENT feature-key-cn (#PCDATA)>
+<!ELEMENT feature-root-cn (#PCDATA)>
+<!ELEMENT feature-root-fingerprint (#PCDATA)>
+
--- /dev/null
+* Fri Mar 07 2014 brianjjones <brian.j.jones@intel.com> 54b2161
+- Initial checkin of the wrt-plugins-ivi-hfp for the HTML5 UI
+
--- /dev/null
+Name: wrt-plugins-ivi-phone
+Summary: JavaScript plugin to access Phone for WebRuntime
+Version: 0.8.5
+Release: 1
+Group: Development/Libraries
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+
+BuildRequires: pkgconfig(ewebkit2)
+BuildRequires: pkgconfig(dpl-efl)
+BuildRequires: pkgconfig(dpl-event-efl)
+BuildRequires: pkgconfig(wrt-plugins-commons)
+BuildRequires: pkgconfig(wrt-plugins-commons-javascript)
+BuildRequires: wrt-plugins-tizen-devel
+BuildRequires: expat-devel
+BuildRequires: cmake
+BuildRequires: gettext-devel
+BuildRequires: pkgconfig(json-glib-1.0)
+
+%description
+JavaScript plugin to access Phone for WebRuntime
+
+%package devel
+Summary: Wrt-plugins-ivi-phone development headers
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description devel
+Wrt-plugins-ivi-phone development headers
+
+%prep
+%setup -q
+
+%build
+
+%define PREFIX "%{_libdir}/wrt-plugins"
+
+export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed"
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DDPL_LOG="ON" -DENABLE_TIME_TRACER="OFF"
+
+make %{?jobs:-j%jobs} VERBOSE=1
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+wrt-installer -p
+
+%postun
+
+%files
+%manifest wrt-plugins-ivi-phone.manifest
+%{_libdir}/wrt-plugins/*
+/usr/etc/tizen-apis/*
+
+%files devel
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
--- /dev/null
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=phone
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: icu-i18n icu-io icu-le icu-lx icu-uc
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
--- /dev/null
+#include "JSPhone.h"
+#include "Phone.h"
+
+#include <Logger.h>
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/Utils.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <dpl/scoped_ptr.h>
+#include <sstream>
+#include <map>
+
+#include <json-glib/json-gvariant.h>
+
+namespace DeviceAPI {
+namespace Phone {
+
+using namespace DPL;
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+#define PHONE_ACTIVECALL_PROP "activeCall"
+
+JSClassDefinition JSPhone::m_classInfo = {
+ 0,
+ kJSClassAttributeNone,
+ "Phone",
+ 0,
+ m_property,
+ m_function,
+ initialize,
+ finalize,
+ NULL, //HasProperty,
+ NULL, //GetProperty,
+ NULL, //SetProperty,
+ NULL, //DeleteProperty,
+ NULL, //GetPropertyNames,
+ NULL, //CallAsFunction,
+ NULL, //CallAsConstructor,
+ hasInstance,
+ NULL, //ConvertToType
+};
+
+JSStaticFunction JSPhone::m_function[] = {
+ { "invokeCall", JSPhone::invokeCall, kJSPropertyAttributeNone },
+ { "answerCall", JSPhone::answerCall, kJSPropertyAttributeNone },
+ { "hangupCall", JSPhone::hangupCall, kJSPropertyAttributeNone },
+ { "muteCall", JSPhone::muteCall, kJSPropertyAttributeNone },
+ { "selectRemoteDevice", JSPhone::selectRemoteDevice, kJSPropertyAttributeNone },
+ { "unselectRemoteDevice", JSPhone::unselectRemoteDevice, kJSPropertyAttributeNone },
+ { "addRemoteDeviceSelectedListener", JSPhone::addRemoteDeviceSelectedListener, kJSPropertyAttributeNone },
+ { "removeRemoteDeviceSelectedListener", JSPhone::removeRemoteDeviceSelectedListener, kJSPropertyAttributeNone },
+ { "getSelectedRemoteDevice", JSPhone::getSelectedRemoteDevice, kJSPropertyAttributeNone },
+ { "getContacts", JSPhone::getContacts, kJSPropertyAttributeNone },
+ { "addContactsChangedListener", JSPhone::addContactsChangedListener, kJSPropertyAttributeNone },
+ { "removeContactsChangedListener", JSPhone::removeContactsChangedListener, kJSPropertyAttributeNone },
+ { "getCallHistory", JSPhone::getCallHistory, kJSPropertyAttributeNone },
+ { "addCallHistoryChangedListener", JSPhone::addCallHistoryChangedListener, kJSPropertyAttributeNone },
+ { "removeCallHistoryChangedListener", JSPhone::removeCallHistoryChangedListener, kJSPropertyAttributeNone },
+ { "addCallChangedListener", JSPhone::addCallChangedListener, kJSPropertyAttributeNone },
+ { "removeCallChangedListener", JSPhone::removeCallChangedListener, kJSPropertyAttributeNone },
+ { "addCallHistoryEntryAddedListener", JSPhone::addCallHistoryEntryAddedListener, kJSPropertyAttributeNone },
+ { "removeCallHistoryEntryAddedListener", JSPhone::removeCallHistoryEntryAddedListener, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+JSStaticValue JSPhone::m_property[] = {
+ {PHONE_ACTIVECALL_PROP, getProperty, NULL, kJSPropertyAttributeNone},
+ { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSPhone::getClassRef()
+{
+ if (!m_jsClassRef)
+ {
+ m_jsClassRef = JSClassCreate(&m_classInfo);
+ }
+ return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPhone::getClassInfo()
+{
+ return &m_classInfo;
+}
+
+JSValueRef JSPhone::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ LoggerD("Enter");
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(object));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ Try {
+ if (JSStringIsEqualToUTF8CString(propertyName, PHONE_ACTIVECALL_PROP)) {
+ PhonePtr phone(privateObject->getObject());
+ JSStringRef state = JSStringCreateWithUTF8CString(phone->activeCall().c_str());
+ JSValueRef result = JSValueMakeFromJSONString(context, state);
+ return result;
+ }
+ } catch (...) {
+ return JSValueMakeUndefined(context);
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+JSClassRef JSPhone::m_jsClassRef = JSClassCreate(JSPhone::getClassInfo());
+
+void JSPhone::initialize(JSContextRef context, JSObjectRef object)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* priv = static_cast<PhonePrivObject*>(JSObjectGetPrivate(object));
+ if (!priv)
+ {
+ PhonePtr phone(new PhoneMaster());
+ priv = new PhonePrivObject( context, phone);
+ if(!JSObjectSetPrivate(object, static_cast<void*>(priv)))
+ {
+ LoggerE("Object can't store private data.");
+ delete priv;
+ }
+ }
+
+ LoggerD("JSPhone::initialize ");
+}
+
+void JSPhone::finalize(JSObjectRef object)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* priv = static_cast<PhonePrivObject*>(JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, NULL);
+ LoggerD("Deleting timeutil");
+ delete priv;
+}
+
+bool JSPhone::hasInstance(JSContextRef context,
+ JSObjectRef constructor,
+ JSValueRef possibleInstance,
+ JSValueRef* exception)
+{
+ return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+JSValueRef JSPhone::invokeCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+ std::string phoneNumber = validator.toString(0);
+ LoggerD("Dialing phone number: " << phoneNumber);
+
+ JSObjectRef errorCallback = validator.toFunction(1, false);
+
+ JSValueProtect(context, errorCallback);
+
+ phone->invokeCall(phoneNumber, errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::hangupCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef errorCallback = validator.toFunction(0, false);
+
+ JSValueProtect(context, errorCallback);
+
+ phone->hangupCall(errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::answerCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef errorCallback = validator.toFunction(0, false);
+
+ JSValueProtect(context, errorCallback);
+
+ phone->answerCall(errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::muteCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+ bool mute = validator.toBool(0);
+ JSObjectRef errorCallback = validator.toFunction(1, false);
+ JSValueProtect(context, errorCallback);
+
+ phone->muteCall(mute, errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::getContacts(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ unsigned long count = validator.toULong(0);
+ LoggerD("Retrieving contacts - the latest " << count << " contacts");
+ JSObjectRef successCallback = validator.toFunction(1, false);
+ JSObjectRef errorCallback = validator.toFunction(2, false);
+
+ JSValueProtect(context, successCallback);
+ JSValueProtect(context, errorCallback);
+
+ phone->getContacts(count, successCallback, errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::getCallHistory(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ unsigned long count = validator.toULong(0);
+ LoggerD("Retrieving call history - the latest " << count << " calls");
+ JSObjectRef successCallback = validator.toFunction(1, false);
+ JSObjectRef errorCallback = validator.toFunction(2, false);
+
+ JSValueProtect(context, successCallback);
+ JSValueProtect(context, errorCallback);
+
+ phone->getCallHistory(count, successCallback, errorCallback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::addCallChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef callback = validator.toFunction(0, false);
+
+ JSValueProtect(gContext, callback);
+
+ int id = phone->addCallChangedListener(callback, gContext);
+ if(id>0)
+ return JSValueMakeNumber(context, id);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::selectRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+ std::string btAddress = validator.toString(0);
+ LoggerD("Selecting device: " << btAddress);
+
+ phone->selectRemoteDevice(btAddress);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::unselectRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ LoggerD("Un-selecting selected device");
+
+ phone->unselectRemoteDevice();
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::addRemoteDeviceSelectedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+ JSObjectRef callback = validator.toFunction(0, false);
+ JSValueProtect(gContext, callback);
+
+ int id = phone->addRemoteDeviceSelectedListener(callback, gContext);
+ if(id>0)
+ return JSValueMakeNumber(context, id);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::removeRemoteDeviceSelectedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ int id = validator.toNumber(0);
+
+ phone->removeRemoteDeviceSelectedListener(id, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::getSelectedRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+ JSContextRef gContext = privateObject->getContext();
+ ArgumentValidator validator(context, argumentCount, arguments);
+ JSObjectRef callback = validator.toFunction(0, false);
+ JSValueProtect(gContext, callback);
+ phone->getSelectedRemoteDevice(callback, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::removeCallChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ int id = validator.toNumber(0);
+
+ phone->removeCallChangedListener(id, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::addCallHistoryEntryAddedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef callback = validator.toFunction(0, false);
+
+ JSValueProtect(gContext, callback);
+
+ int id = phone->addCallHistoryEntryAddedListener(callback, gContext);
+ if(id>0)
+ return JSValueMakeNumber(context, id);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::removeCallHistoryEntryAddedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ int id = validator.toNumber(0);
+
+ phone->removeCallHistoryEntryAddedListener(id, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::addContactsChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef callback = validator.toFunction(0, false);
+
+ JSValueProtect(gContext, callback);
+
+ int id = phone->addContactsChangedListener(callback, gContext);
+ if(id>0)
+ return JSValueMakeNumber(context, id);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::removeContactsChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ int id = validator.toNumber(0);
+
+ phone->removeContactsChangedListener(id, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::addCallHistoryChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ JSObjectRef callback = validator.toFunction(0, false);
+
+ JSValueProtect(gContext, callback);
+
+ int id = phone->addCallHistoryChangedListener(callback, gContext);
+ if(id>0)
+ return JSValueMakeNumber(context, id);
+
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPhone::removeCallHistoryChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception)
+{
+ LoggerD("Entered");
+
+ PhonePrivObject* privateObject = static_cast<PhonePrivObject*>(JSObjectGetPrivate(thisObject));
+ if (NULL == privateObject)
+ {
+ LoggerE("private object is null");
+ return JSValueMakeUndefined(context);
+ }
+
+ PhonePtr phone(privateObject->getObject());
+
+ JSContextRef gContext = privateObject->getContext();
+
+ ArgumentValidator validator(context, argumentCount, arguments);
+
+ int id = validator.toNumber(0);
+
+ phone->removeCallHistoryChangedListener(id, gContext);
+
+ return JSValueMakeUndefined(context);
+}
+
+} // Phone
+} // DeviceAPI
+
--- /dev/null
+#ifndef JSPHONE_H
+#define JSPHONE_H
+
+#include "Phone.h"
+#include <dpl/shared_ptr.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/JSPendingOperationPrivateObject.h>
+#include <CommonsJavaScript/PrivateObject.h>
+
+namespace DeviceAPI {
+namespace Phone {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<PhonePtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> PhonePrivObject;
+
+/**
+ * @defgroup wrt-plugins-ivi-phone wrt-plugins-ivi-phone shared library
+ * \brief WebAPI to provide access to phone's functionality.
+ *
+ * WebAPI to provide access to phone's functionality, such as invoke phone call, accept/decline incoming call, hangup active call, retrieve a list of contacts stored in internal memory of a phone device, as well as its call history.
+ * @{
+ */
+
+/*! \class DeviceAPI::Phone::JSPhone
+ * \brief A Class which implements \b tizen.phone object to access phone's functionality from within Web app.
+ *
+ * A Class which implements \b tizen.phone object to access phone's functionality from within Web app.
+ *
+ * It defines the following methods on \b tizen.phone:
+ * <ul>
+ <li> \b selectRemoteDevice ( \a \b address ) Selects remote BT device for phone's operations. Once remote device gets selected, a listener registered by addRemoteDeviceSelectedListener() is called, passing a MAC address of selected remote device to indicate the success of the method call. </li>
+ <ul>
+ <li> \a \b address A MAC address of remote device to be selected. </li>
+ </ul>
+
+ <li> \b unselectRemoteDevice () Unselects remote BT device selected by selectRemoteDevice(). Once remote device gets unselected, a listener registered by addRemoteDeviceSelectedListener() is called, passing \b "" to indicate that there is no currently selected remote device for phone's operations. </li>
+
+ <li> \b getSelectedRemoteDevice ( \a \b callback ) Method to get currently selected remote device. </li>
+ <ul>
+ <li> \a \b callback ( \a \b address ) A callback to invoke when the remote device is retrieved. </li>
+ <ul>
+ <li>\a \b address A MAC address of selected remote device. If there is no currently selected remote device, \b "" is returned. </li>
+ </ul>
+ </ul>
+
+ <li> \b addRemoteDeviceSelectedListener ( \a \b listener ) Adds a listener to get notifified when selected remote device has changed. </li>
+ <ul>
+ <li> \a \b listener ( \a \b address ) A listener to call when the remote device has changed. </li>
+ <ul>
+ <li>\a \b address A MAC address of selected remote device. Empty string \b "" means no currently selected remote device. </li>
+ </ul>
+ <li>\a \b returns Id of registered listener. </li>
+ </ul>
+
+ <li> \b removeRemoteDeviceSelectedListener ( \a \b id ) Removes a listener previously registered by addRemoteDeviceSelectedListener(). </li>
+ <ul>
+ <li> \a \b id An id of registered listener to be removed. </li>
+ </ul>
+
+ <li> \b invokeCall ( \a \b number, \a \b errorCallback ) Dials a given phone number. </li>
+ <ul>
+ <li> \a \b number A phone number to dial. </li>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when dialing has failed.
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b answerCall ( \a \b errorCallback ) Answers incoming phone call. </li>
+ <ul>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when answering the call has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b hangupCall ( \a \b errorCallback ) Declines incoming phone call, or hangs-up active one. </li>
+ <ul>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when hanging-up the call has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b muteCall ( \a \b mute, \a \b errorCallback ) Mutes/unmutes the active phone call. </li>
+ <ul>
+ <li> \a \b mute Whether to mute, or unmute the active phone call. </li>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when muting the call has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b activeCall () Returns active phone call. </li>
+ <ul>
+ <li> \a \b returns Returns active phone call. The active call object contains attributes \b line_id specifying phone number of caller, or calling person respectively, \b state which specify the state of the call and \b contact which matches the \b line_id. If there is no active call, \b line_id is set to \b "" and \b state is set to \b "disconnected". </li>
+ </ul>
+
+ <li> \b addCallChangedListener ( \a \b listener ) Adds a listener to get notifified when there is a change on active call, ie. to get notified about incoming call and all other states that the call may go through, up to \b "disconnected" state. </li>
+ <ul>
+ <li> \a \b listener ( \a \b call ) A listener to call when there is a change on the active call. </li>
+ <ul>
+ <li>\a \b call The call object contains attributes \b line_id specifying phone number of caller, or calling person respectively, \b state which specify the state of the call and \b contact which matches the \b line_id. If there is no active call, \b line_id is set to \b "" and \b state is set to \b "disconnected". </li>
+ </ul>
+ <li>\a \b returns Id of registered listener. </li>
+ </ul>
+
+ <li> \b removeCallChangedListener ( \a \b id ) Removes a listener previously registered by addCallChangedListener(). </li>
+ <ul>
+ <li> \a \b id An id of registered listener to be removed. </li>
+ </ul>
+
+ <li> \b getContacts ( \a \b count, \a \b successCallback, \a \b errorCallback ) Retrieves an array of \a \b count synchronized contacts in JSON \b tizen.Contact format. </li>
+ <ul>
+ <li> \a \b count Specifies \a \b count the frist contacts to retrieve. \b 0 means to retrieve all contacts. </li>
+ <li> \a \b successCallback ( \a \b contacts ) A callback to call when contacts are successfuly retrieved. </li>
+ <ul>
+ <li>\a \b contacts An array of retrieved contacts in \b tizen.Contact JSON format. </li>
+ </ul>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when retrieving the contacts has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b getCallHistory ( \a \b count, \a \b successCallback, \a \b errorCallback ) Retrieves an array of \a \b count synchronized call history entries in JSON \b tizen.CallHistoryEntry format. </li>
+ <ul>
+ <li> \a \b count Specifies \a \b count the frist call history entries to retrieve. \b 0 means to retrieve all calls. </li>
+ <li> \a \b successCallback ( \a \b contacts ) A callback to call when contacts are successfuly retrieved. </li>
+ <ul>
+ <li>\a \b contacts An array of retrieved call history entries in \b tizen.CallHistoryEntry JSON format. </li>
+ </ul>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when retrieving the call history entries has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b addCallHistoryEntryAddedListener ( \a \b listener ) Adds a listener to get notifified when a call entry has been added to the history list, due to incoming, or dialed call. </li>
+ <ul>
+ <li> \a \b listener ( \a \b call ) A listener to call when the call history entry was added to the list. </li>
+ <ul>
+ <li>\a \b call Call history entry added to the history list. </li>
+ </ul>
+ <li>\a \b returns Id of registered listener. </li>
+ </ul>
+
+ <li> \b removeCallHistoryEntryAddedListener ( \a \b id ) Removes a listener previously registered by addCallHistoryEntryAddedListener(). </li>
+ <ul>
+ <li> \a \b id An id of registered listener to be removed. </li>
+ </ul>
+
+ <li> \b addContactsChangedListener ( \a \b listener ) Adds a listener to get notifified when contacts list has changed, ie. when a new contact was added, or if the list was cleared. </li>
+ <ul>
+ <li> \a \b listener () A listener to call when the contacts list has changed. </li>
+ <li>\a \b returns Id of registered listener. </li>
+ </ul>
+
+ <li> \b removeContactsChangedListener ( \a \b id ) Removes a listener previously registered by addContactsChangedListener(). </li>
+ <ul>
+ <li> \a \b id An id of registered listener to be removed. </li>
+ </ul>
+
+ <li> \b addCallHistoryChangedListener ( \a \b listener ) Adds a listener to get notifified when call history list has changed, ie. when a new call history entry was added, or if the list was cleared. </li>
+ <ul>
+ <li> \a \b listener () A listener to call when the call history list has changed. </li>
+ <li>\a \b returns Id of registered listener. </li>
+ </ul>
+
+ <li> \b removeCallHistoryChangedListener ( \a \b id ) Removes a listener previously registered by addCallHistoryChangedListener(). </li>
+ <ul>
+ <li> \a \b id An id of registered listener to be removed. </li>
+ </ul>
+
+ <li> \b createBonding ( \a \b address, \a \b successCallback, \a \b errorCallback ) Initiates a pairing sequence with the remote BT device, specified by it's MAC address. </li>
+ <ul>
+ <li> \a \b address A MAC address of remote device to pair with. </li>
+ <li> \a \b successCallback () A callback to invoke when the pairing has successfuly finished. </li>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when pairing with remote BT address has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+
+ <li> \b destroyBonding ( \a \b address, \a \b successCallback, \a \b errorCallback ) Unpairs with the remote BT device, specified by it's MAC address. </li>
+ <ul>
+ <li> \a \b address A MAC address of remote device to unpair with. </li>
+ <li> \a \b successCallback () A callback to invoke when the pairing has successfuly finished. </li>
+ <li> \a \b errorCallback ( \a \b error ) A callback to invoke when unpairing with remote BT address has failed. </li>
+ <ul>
+ <li> \a \b error A JSON object describing the reason of failure. It contains a \a \b message attribute holding a string representation of failure. </li>
+ </ul>
+ </ul>
+ * </ul>
+ */
+class JSPhone
+{
+public:
+ /**
+ * Gets the Call Definition.
+ * @see getClassRef()
+ * @return JS class definition.
+ */
+ static const JSClassDefinition* getClassInfo();
+
+ /**
+ * Method to create (if it's not yet created) and return this class reference. Used by the plugin loader to load this plugin.
+ * @see getClassInfo()
+ * @return JS class reference.
+ */
+ static const JSClassRef getClassRef();
+
+private:
+ /**
+ * The callback invoked when an object is first created.
+ */
+ static void initialize(JSContextRef context,
+ JSObjectRef object);
+
+ /**
+ * The callback invoked when an object is finalized.
+ */
+ static void finalize(JSObjectRef object);
+
+ /**
+ * Getters for properties
+ */
+ static JSValueRef getProperty(JSContextRef context,
+ JSObjectRef object,
+ JSStringRef propertyName,
+ JSValueRef* exception);
+
+ /**
+ * The callback invoked when an object is used as the target of an 'instanceof' expression.
+ */
+ static bool hasInstance(JSContextRef ctx,
+ JSObjectRef constructor,
+ JSValueRef possibleInstance,
+ JSValueRef* exception);
+
+ /**
+ * Invoke phone call on BT paired device
+ */
+ static JSValueRef invokeCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Hangup (active/incoming, dialing) phone call.
+ */
+ static JSValueRef hangupCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Answer (incoming) phone call.
+ */
+ static JSValueRef answerCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Mute/UnMute phone call.
+ */
+ static JSValueRef muteCall(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Selects a remote BT device for Phone operations
+ * btAddress: address of paired and trusted BT device
+ * the client app should subscribe for RemoteDeviceSelected signal, ie. should call addRemoteDeviceSelectedListener()
+ * see addRemoteDeviceSelectedListener for more information
+ */
+ static JSValueRef selectRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Un-selects selected remote BT device for Phone operations
+ * the client app should subscribe for RemoteDeviceSelected signal, ie. should call addRemoteDeviceSelectedListener()
+ * see addRemoteDeviceSelectedListener for more information
+ */
+ static JSValueRef unselectRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Adds listener to get notified about the result of selecting remote device
+ * parameter to the callback defines result of operation:
+ * if result contains 'error' atribute, it contains error meessage of the failure
+ * if resutl contains 'value' and if value is "<SOME_MAC_ADDRESS>" - it holds a MAC address of selected device
+ * if resutl contains 'value' and if value is "" - it indicates that the remote device is unselected
+ * services OFono/Obex are up and running
+ * returns id of registered listener, to be used for removing
+ */
+ static JSValueRef addRemoteDeviceSelectedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Removes listener for notification about selected remote device.
+ * parameter is id of listener registered via addRemoteDeviceSelectedListener()
+ */
+ static JSValueRef removeRemoteDeviceSelectedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Get selected remote BT device
+ * returns: MAC address of selected remote BT device
+ */
+ static JSValueRef getSelectedRemoteDevice(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Retrieve contacts from BT paired device: the latest 'count' entries
+ */
+ static JSValueRef getContacts(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Retrieve call history: the latest 'count' entries
+ */
+ static JSValueRef getCallHistory(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Adds listener for property changed on active call
+ * returns id of registered listener, to be used for removing
+ */
+ static JSValueRef addCallChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Removes listener for property changed on active call.
+ * parameter is id of listener registered via addCallCangedListener()
+ */
+ static JSValueRef removeCallChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Adds listener to get notified about an Call entry being added to the Call History
+ * returns id of registered listener, to be used for removing
+ */
+ static JSValueRef addCallHistoryEntryAddedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Removes listener for notification about call entry being added to the Call History
+ * parameter is id of listener registered via addCallHistoryEntryAddedListener()
+ */
+ static JSValueRef removeCallHistoryEntryAddedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Adds listener to get notified about an Contacts being changed - as a result of selectRemoteDevice
+ * returns id of registered listener, to be used for removing
+ */
+ static JSValueRef addContactsChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Removes listener for notification about contacts being changed (as a result of selectRemoteDevice)
+ * parameter is id of listener registered via addContactsChangedListener()
+ */
+ static JSValueRef removeContactsChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Adds listener to get notified about an CallHistory being changed - as a result of selectRemoteDevice
+ * returns id of registered listener, to be used for removing
+ */
+ static JSValueRef addCallHistoryChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * Removes listener for notification about contacts being changed (as a result of selectRemoteDevice)
+ * parameter is id of listener registered via addCallHistoryChangedListener()
+ */
+ static JSValueRef removeCallHistoryChangedListener(JSContextRef context,
+ JSObjectRef object,
+ JSObjectRef thisObject,
+ size_t argumentCount,
+ const JSValueRef arguments[],
+ JSValueRef* exception);
+
+ /**
+ * This structure contains properties and callbacks that define a type of object.
+ */
+ static JSClassDefinition m_classInfo;
+
+ /**
+ * This structure describes a statically declared function.
+ */
+ static JSStaticFunction m_function[];
+
+ /**
+ * This member variable contains the initialization values for the
+ * properties of this class. The values are given according to the
+ * data structure JSPropertySpec.
+ */
+ static JSStaticValue m_property[];
+
+ static JSClassRef m_jsClassRef;
+};
+
+} // Phone
+} // DeviceAPI
+
+#endif // JSPHONE_H
+
+/** @} */
+
--- /dev/null
+#include "Phone.h"
+#include <gio/gio.h>
+#include <stdexcept>
+#include <Logger.h>
+
+#include <Commons/ThreadPool.h>
+#include <CommonsJavaScript/Converter.h>
+#include <json-glib/json-gvariant.h>
+
+#define TIZEN_PREFIX "org.tizen"
+#define PHONE_SERVICE TIZEN_PREFIX ".phone"
+#define PHONE_IFACE TIZEN_PREFIX ".Phone"
+#define PHONE_OBJ_PATH "/"
+
+#define DEFAULT_PINCODE "123456"
+#define DEFAULT_PASSKEY 123456
+
+namespace DeviceAPI
+{
+namespace Phone
+{
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+PhoneMaster::PhoneMaster()
+{
+ LoggerD("entered");
+}
+
+PhoneMaster::~PhoneMaster()
+{
+ LoggerD("entered");
+}
+
+void PhoneMaster::handleSignal( 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("\tsender_name: " << sender_name);
+ //LoggerD("\tobject_path: " << object_path);
+ //LoggerD("\tinterface_name: " << interface_name);
+ //LoggerD("\tsignal_name: " << signal_name);
+
+ PhoneMaster* ctx = static_cast<PhoneMaster*>(user_data);
+ if(!ctx) {
+ LoggerE("Failed to cast to PhoneMaster ... invalid context");
+ return;
+ }
+
+ if(!strcmp(signal_name, "RemoteDeviceSelected")) {
+ const char *result;
+ g_variant_get(parameters, "(s)", &result);
+ if(result) {
+ if(ctx->mRemoteDeviceSelectedListenersMap.size() > 0) {
+ for(auto it=ctx->mRemoteDeviceSelectedListenersMap.begin(); it!=ctx->mRemoteDeviceSelectedListenersMap.end(); ++it) {
+ PhoneSubscriptionData *data = (*it).second;
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(result);
+ JSValueRef value = JSValueMakeFromJSONString(data->context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ break;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 1, arguments, NULL);
+ }
+ }
+ }
+ }
+ else if(!strcmp(signal_name, "CallChanged")) {
+ GVariantIter *iter;
+ g_variant_get(parameters, "(a{sv})", &iter);
+ const char *key = NULL, *state = NULL, *line_id = NULL, *contact = NULL;
+ GVariant *value;
+ while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+ if(!strcmp(key, "state")) {
+ state = g_variant_get_string(value, NULL);
+ LoggerD("\t- state: " << state);
+ }
+ else if(!strcmp(key, "line_id")) {
+ line_id = g_variant_get_string(value, NULL);
+ LoggerD("\t- line_id: " << line_id);
+ }
+ else if(!strcmp(key, "contact")) {
+ contact = g_variant_get_string(value, NULL);
+ LoggerD("\t- contact: " << contact);
+ }
+ }
+
+ if(ctx->mCallChangedListenersMap.size() > 0) {
+ LoggerD("subscribed for 'CallChanged' ... calling callback");
+ std::string json;
+ json += "{\"line_id\" : \"";
+ json += line_id;
+ json += "\", \"state\" : \"";
+ json += state;
+ json += "\", \"contact\" : ";
+ json += contact;
+ json += "}";
+
+ // call all subscribed listeners
+ std::map<int, PhoneMaster::PhoneSubscriptionData*>::iterator iter = ctx->mCallChangedListenersMap.begin();
+ while(iter != ctx->mCallChangedListenersMap.end()) {
+ PhoneSubscriptionData *data = (*iter).second;
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(data->context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ break;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 1, arguments, NULL);
+ iter++;
+ }
+ }
+ }
+ else if(!strcmp(signal_name, "ContactsChanged")) {
+ if(ctx->mContactsChangedListenersMap.size() > 0) {
+ for(auto it=ctx->mContactsChangedListenersMap.begin(); it!=ctx->mContactsChangedListenersMap.end(); ++it) {
+ PhoneSubscriptionData *data = (*it).second;
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 0, NULL, NULL);
+ }
+ }
+ }
+ else if(!strcmp(signal_name, "CallHistoryChanged")) {
+ if(ctx->mCallHistoryChangedListenersMap.size() > 0) {
+ for(auto it=ctx->mCallHistoryChangedListenersMap.begin(); it!=ctx->mCallHistoryChangedListenersMap.end(); ++it) {
+ PhoneSubscriptionData *data = (*it).second;
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 0, NULL, NULL);
+ }
+ }
+ }
+ else if(!strcmp(signal_name, "CallHistoryEntryAdded")) {
+ const char *call;
+ g_variant_get(parameters, "(s)", &call);
+ if(call) {
+ if(ctx->mCallHistoryEntryAddedListenersMap.size() > 0) {
+ for(auto it=ctx->mCallHistoryEntryAddedListenersMap.begin(); it!=ctx->mCallHistoryEntryAddedListenersMap.end(); ++it) {
+ PhoneSubscriptionData *data = (*it).second;
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(call);
+ JSValueRef value = JSValueMakeFromJSONString(data->context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ break;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 1, arguments, NULL);
+ }
+ }
+ }
+ }
+ else {
+ LoggerD("Unhandled signal: " << signal_name);
+ }
+}
+
+void PhoneMaster::invokeCall(std::string phoneNumber, JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "Dial",
+ g_variant_new("(s)", phoneNumber.c_str()), // floating variants are consumed
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if(error) {
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ //json += error->code;
+ json += "1";
+ json += "\", \"message\" : \"DBUS: ";
+ json += error->message;
+ json += "\"}";
+
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+}
+
+void PhoneMaster::hangupCall(JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "Hangup",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if(error) {
+ LoggerE("Failed to hangup call: " << error->message);
+
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ //json += error->code;
+ json += "1";
+ json += "\", \"message\" : \"DBUS: ";
+ json += error->message;
+ json += "\"}";
+
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+}
+
+void PhoneMaster::answerCall(JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "Answer",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if(error) {
+ LoggerE("Failed to answer call: " << error->message);
+
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ //json += error->code;
+ json += "1";
+ json += "\", \"message\" : \"DBUS: ";
+ json += error->message;
+ json += "\"}";
+
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+}
+
+void PhoneMaster::muteCall(bool mute, JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "Mute",
+ g_variant_new("(b)", mute), // floating variants are consumed
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if(error) {
+ LoggerE("Failed to mute call: " << error->message);
+
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ //json += error->code;
+ json += "1";
+ json += "\", \"message\" : \"DBUS: ";
+ json += error->message;
+ json += "\"}";
+
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+}
+
+void PhoneMaster::selectRemoteDevice(std::string btAddress) {
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "SelectRemoteDevice",
+ g_variant_new("(s)", btAddress.c_str()), // floating variants are consumed
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if(error) {
+ LoggerE("Failed to call 'SelectremoteDevice': " << error->message);
+ g_error_free(error);
+ }
+}
+
+void PhoneMaster::unselectRemoteDevice() {
+ GError *error = NULL;
+ g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "UnselectRemoteDevice",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if(error) {
+ LoggerE("Failed to call 'UnselectremoteDevice': " << error->message);
+ g_error_free(error);
+ }
+}
+
+void PhoneMaster::getContacts(unsigned long count, JSObjectRef successCallback, JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ GVariant *reply = NULL;
+ reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "GetContacts",
+ g_variant_new("(u)", count),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ /* for async DBUS call
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ data->context = context;
+ data->callback = successCallback;
+ data->errorCallback = errorCallback;
+ */
+
+ if(error || !reply) {
+ if(error)
+ LoggerE("Failed to get contacts: " << error->message);
+ if(!reply)
+ LoggerE("reply is null");
+
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ json += error ? 1 : 2;
+ json += "\", \"message\" : \"DBUS: ";
+ json += error ? "Failed to 'GetContacts'" : "Reply from 'GetContacts' is null";
+ json += "\"}";
+
+ if(error)
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+
+ char *contacts = NULL;
+ g_variant_get(reply, "(s)", &contacts);
+
+ JSStringRef str = JSStringCreateWithUTF8CString(contacts);
+ JSValueRef value = JSValueMakeFromJSONString(context, str);
+ if(!value)
+ {
+ std::string json;
+ json += "{\"code\" : \"";
+ json += 2;
+ json += "\", \"message\" : \"";
+ json += "Unable to create response value.";
+ json += "\"}";
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("Failed to make value from json");
+ // !!! it's bad !!! no callback is called !!!
+ // TODO: should we call error callback with 'undefined' value instead?
+ g_variant_unref(reply);
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, successCallback, NULL, 1, arguments, NULL);
+ g_variant_unref(reply);
+}
+
+void PhoneMaster::getCallHistory(unsigned long count, JSObjectRef successCallback, JSObjectRef errorCallback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ GError *error = NULL;
+ GVariant *reply = NULL;
+ reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "GetCallHistory",
+ g_variant_new("(u)", count),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ /* for async DBUS call
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ data->context = context;
+ data->callback = successCallback;
+ data->errorCallback = errorCallback;
+ */
+
+ if(error || !reply) {
+ if(error)
+ LoggerE("Failed to get call history: " << error->message);
+ if(!reply)
+ LoggerE("reply is null");
+
+ // call the error callback to notify client about the error condition
+ std::string json;
+ json += "{\"code\" : \"";
+ json += error ? 1 : 2;
+ json += "\", \"message\" : \"DBUS: ";
+ json += error ? "Failed to 'GetCallHistory'" : "Reply from 'GetCallHistory' is null";
+ json += "\"}";
+
+ if(error)
+ g_error_free(error);
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("failed to make value from json");
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+
+ char *calls = NULL;
+ g_variant_get(reply, "(s)", &calls);
+
+ JSStringRef str = JSStringCreateWithUTF8CString(calls);
+ JSValueRef value = JSValueMakeFromJSONString(context, str);
+ if(!value)
+ {
+ std::string json;
+ json += "{\"code\" : \"";
+ json += 2;
+ json += "\", \"message\" : \"";
+ json += "Unable to create response value.";
+ json += "\"}";
+
+ JSStringRef jsonString = JSStringCreateWithUTF8CString(json.c_str());
+ JSValueRef value = JSValueMakeFromJSONString(context, jsonString);
+ if(!value)
+ {
+ LoggerE("Failed to make value from json");
+ // !!! it's bad !!! no callback is called !!!
+ // TODO: should we call error callback with 'undefined' value instead?
+ g_variant_unref(reply);
+ return;
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, errorCallback, NULL, 1, arguments, NULL);
+ }
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(context, successCallback, NULL, 1, arguments, NULL);
+ g_variant_unref(reply);
+}
+
+int PhoneMaster::addRemoteDeviceSelectedListener(JSObjectRef callback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ guint id = 0;
+ if(mRemoteDeviceSelectedListenersMap.size() == 0) {
+ // we are not yet subscribed to the signal
+ id = g_dbus_connection_signal_subscribe( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_IFACE,
+ "RemoteDeviceSelected",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ handleSignal,
+ this,
+ NULL);
+ if(id <= 0) {
+ LoggerE("Failed to subscribe for 'RemoteDeviceSelected': " << id);
+ return -1;
+ }
+ }
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ if(!data) {
+ // unsubscribe the signal, othewise we will have 'unhandled' signal
+ LoggerE("Unable to create subscription data ... removing subscription with id: " << id);
+ g_dbus_connection_signal_unsubscribe(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL), id);
+ return -2;
+ }
+ data->context = context;
+ data->callback = callback;
+
+ mRemoteDeviceSelectedListenersMap[id] = data;
+
+ return id;
+}
+
+void PhoneMaster::removeRemoteDeviceSelectedListener(int id, JSContextRef context)
+{
+ LoggerD("removing listener id=" << id);
+
+ mRemoteDeviceSelectedListenersMap.erase(id);
+}
+
+int PhoneMaster::addCallChangedListener(JSObjectRef callback, JSContextRef context)
+{
+ LoggerD("adding listener for CallChanged");
+
+ // we are not yet subscribed to ofono's CallChanged signal
+ guint id = 0;
+ if(mCallChangedListenersMap.size() == 0) {
+ id = g_dbus_connection_signal_subscribe( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_IFACE,
+ "CallChanged",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ handleSignal,
+ this,
+ NULL);
+ if(id <= 0) {
+ LoggerE("Failed to subscribe for 'CallChanged': " << id);
+ return -1;
+ }
+ }
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ if(!data) {
+ // unsubscribe the signal, othewise we will have 'unhandled' signal
+ LoggerE("Unable to create subscription data ... removing subscription with id: " << id);
+ g_dbus_connection_signal_unsubscribe(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL), id);
+ return -2;
+ }
+ data->context = context;
+ data->callback = callback;
+
+ mCallChangedListenersMap[id] = data;
+
+ return id;
+}
+
+void PhoneMaster::removeCallChangedListener(int id, JSContextRef context)
+{
+ LoggerD("removing listener id=" << id);
+
+ mCallChangedListenersMap.erase(id);
+}
+
+int PhoneMaster::addCallHistoryEntryAddedListener(JSObjectRef callback, JSContextRef context)
+{
+ LoggerD("adding listener for CallHistoryEntryAdded");
+
+ guint id = 0;
+ if(mCallHistoryEntryAddedListenersMap.size() == 0) {
+ // we are not yet subscribed to the signal
+ id = g_dbus_connection_signal_subscribe( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_IFACE,
+ "CallHistoryEntryAdded",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ handleSignal,
+ this,
+ NULL);
+ if(id <= 0) {
+ LoggerE("Failed to subscribe for 'CallHistoryEntryAdded': " << id);
+ return -1;
+ }
+ }
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ if(!data) {
+ // unsubscribe the signal, othewise we will have 'unhandled' signal
+ LoggerE("Unable to create subscription data ... removing subscription with id: " << id);
+ g_dbus_connection_signal_unsubscribe(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL), id);
+ return -2;
+ }
+ data->context = context;
+ data->callback = callback;
+
+ mCallHistoryEntryAddedListenersMap[id] = data;
+
+ return id;
+}
+
+void PhoneMaster::removeCallHistoryEntryAddedListener(int id, JSContextRef context)
+{
+ LoggerD("removing listener id=" << id);
+
+ mCallHistoryEntryAddedListenersMap.erase(id);
+}
+
+int PhoneMaster::addContactsChangedListener(JSObjectRef callback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ guint id = 0;
+ if(mContactsChangedListenersMap.size() == 0) {
+ // we are not yet subscribed to the signal
+ id = g_dbus_connection_signal_subscribe( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_IFACE,
+ "ContactsChanged",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ handleSignal,
+ this,
+ NULL);
+ if(id <= 0) {
+ LoggerE("Failed to subscribe for 'ContactsChanged': " << id);
+ return -1;
+ }
+ }
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ if(!data) {
+ // unsubscribe the signal, othewise we will have 'unhandled' signal
+ LoggerE("Unable to create subscription data ... removing subscription with id: " << id);
+ g_dbus_connection_signal_unsubscribe(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL), id);
+ return -2;
+ }
+ data->context = context;
+ data->callback = callback;
+
+ mContactsChangedListenersMap[id] = data;
+
+ return id;
+}
+
+void PhoneMaster::removeContactsChangedListener(int id, JSContextRef context)
+{
+ LoggerD("removing listener id=" << id);
+
+ mContactsChangedListenersMap.erase(id);
+}
+
+int PhoneMaster::addCallHistoryChangedListener(JSObjectRef callback, JSContextRef context)
+{
+ LoggerD("entered");
+
+ guint id = 0;
+ if(mCallHistoryChangedListenersMap.size() == 0) {
+ // we are not yet subscribed to the signal
+ id = g_dbus_connection_signal_subscribe( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL),
+ PHONE_SERVICE,
+ PHONE_IFACE,
+ "CallHistoryChanged",
+ NULL,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ handleSignal,
+ this,
+ NULL);
+ if(id <= 0) {
+ LoggerE("Failed to subscribe for 'CallHistoryChanged': " << id);
+ return -1;
+ }
+ }
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ if(!data) {
+ // unsubscribe the signal, othewise we will have 'unhandled' signal
+ LoggerE("Unable to create subscription data ... removing subscription with id: " << id);
+ g_dbus_connection_signal_unsubscribe(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL,NULL), id);
+ return -2;
+ }
+ data->context = context;
+ data->callback = callback;
+
+ mCallHistoryChangedListenersMap[id] = data;
+
+ return id;
+}
+
+void PhoneMaster::removeCallHistoryChangedListener(int id, JSContextRef context)
+{
+ LoggerD("removing listener id=" << id);
+
+ mCallHistoryChangedListenersMap.erase(id);
+}
+
+std::string PhoneMaster::activeCall(void) {
+ LoggerD("entered");
+
+ GError *error = NULL;
+ GVariant *reply = NULL;
+ reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "ActiveCall",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ std::string json;
+ if(error || !reply) {
+ if(error) {
+ LoggerE("Failed to get 'ActiveCall': " << error->message);
+ g_error_free(error);
+ }
+ else if(!reply)
+ LoggerE("reply is null");
+
+ json += "{\"line_id\" : \"";
+ json += "";
+ json += "\", \"state\" : \"";
+ json += "disconnected";
+ json += "\", \"contact\" : \"";
+ json += "{}";
+ json += "\"}";
+ }
+ else {
+ GVariantIter *iter;
+ g_variant_get(reply, "(a{sv})", &iter);
+ const char *key = NULL, *state = NULL, *line_id = NULL, *contact = NULL;
+ GVariant *value;
+ while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+ if(!strcmp(key, "state")) {
+ state = g_variant_get_string(value, NULL);
+ LoggerD("\t- state: " << state);
+ }
+ else if(!strcmp(key, "line_id")) {
+ line_id = g_variant_get_string(value, NULL);
+ LoggerD("\t- line_id: " << line_id);
+ }
+ else if(!strcmp(key, "contact")) {
+ contact = g_variant_get_string(value, NULL);
+ LoggerD("\t- contact: " << contact);
+ }
+ }
+
+ json += "{\"line_id\" : \"";
+ json += line_id;
+ json += "\", \"state\" : \"";
+ json += state;
+ json += "\", \"contact\" : ";
+ json += contact;
+ json += "}";
+
+ g_variant_unref(reply);
+ }
+
+ return json;
+}
+
+void PhoneMaster::getSelectedRemoteDevice(JSObjectRef callback, JSContextRef context) {
+ LoggerD("entered");
+
+ PhoneMaster::PhoneSubscriptionData *data = new PhoneMaster::PhoneSubscriptionData();
+ data->context = context;
+ data->callback = callback;
+ data->errorCallback = NULL;
+
+ g_dbus_connection_call( g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL),
+ PHONE_SERVICE,
+ PHONE_OBJ_PATH,
+ PHONE_IFACE,
+ "GetSelectedRemoteDevice",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ PhoneMaster::asyncGetSelectedRemoteDeviceCB,
+ data);
+}
+
+void PhoneMaster::asyncGetSelectedRemoteDeviceCB(GObject *source, GAsyncResult *result, gpointer user_data) {
+ PhoneMaster::PhoneSubscriptionData *data = static_cast<PhoneMaster::PhoneSubscriptionData*>(user_data);
+ if(!data) {
+ LoggerE("Failed to cast object: PhoneSubscriptionData");
+ return;
+ }
+
+ GError *err = NULL;
+ GVariant *reply;
+ reply = g_dbus_connection_call_finish(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL), result, &err);
+ JSStringRef strRef = JSStringCreateWithUTF8CString("");
+ if(err || !reply) {
+ if(err) {
+ LoggerE("Failed to \"GetSelectedRemoteDevice\": " << err->message);
+ g_error_free(err);
+ }
+ else if(!reply)
+ LoggerE("reply is null");
+ }
+ else {
+ const char *str;
+ g_variant_get(reply, "(s)", &str);
+ if(str)
+ strRef = JSStringCreateWithUTF8CString(str);
+ }
+
+ JSValueRef value = JSValueMakeString(data->context, strRef);
+ const JSValueRef arguments[1] = { value };
+ JSObjectCallAsFunction(data->context, data->callback, NULL, 1, arguments, NULL);
+ delete data;
+ if(reply)
+ g_variant_unref(reply);
+}
+
+} // Phone
+} // DeviceAPI
+
--- /dev/null
+#ifndef PHONE_H
+#define PHONE_H
+
+#include <string>
+#include <dpl/mutex.h>
+#include <dpl/shared_ptr.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <gio/gio.h>
+#include <map>
+
+class AbstractPropertyType;
+
+namespace DeviceAPI {
+namespace Phone {
+
+/**
+ * @addtogroup wrt-plugins-ivi-phone
+ *
+ * @{
+ */
+
+/*! \class DeviceAPI::Phone::PhoneMaster
+ * \brief Class which is utilizing Phone D-Bus service.
+ *
+ * A Class which is utilizing Phone D-Bus service. It connects to \b org.tizen.phone D-Bus service, subscribes to it's signals and implements methods to allow JSPhone to access phone's functionality.
+ */
+class PhoneMaster
+{
+ /**
+ * A helper class to store context/callback for asynchronous operations.
+ */
+ class PhoneSubscriptionData
+ {
+ public:
+ JSContextRef context; /*!< A variable to store context. */
+ JSObjectRef callback; /*!< A variable to store callback. */
+ JSObjectRef errorCallback; /*!< A variable to store error callback. */
+ };
+public:
+
+ /**
+ * A default constructor. Constructs the object.
+ */
+ PhoneMaster();
+
+ /**
+ * A destructor. Destructs the object.
+ */
+ ~PhoneMaster();
+
+ /**
+ * Selects remote BT device for phone's operations.
+ * @param[in] btAddress A MAC address of the remote device to get selected. Will call a listener registered by addRemoteDeviceSelectedListener().
+ */
+ void selectRemoteDevice(std::string btAddress);
+
+ /**
+ * Unselects remote BT device selected by selectRemoteDevice(). Will call a listener registered by addRemoteDeviceSelectedListener().
+ */
+ void unselectRemoteDevice();
+
+ /**
+ * Method to get currently selected remote device.
+ * @param[in] callback A callback to invoke when the remote device is retrieved, passing a MAC address of selected remote device, or \b "" if there is no currently selected remote device.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void getSelectedRemoteDevice(JSObjectRef callback, JSContextRef context);
+
+ /**
+ * Adds a listener to get notifified when selected remote device has changed.
+ * @param[in] callback A listener to call when the remote device has changed.
+ * @param[in] context A context on which the method is invoked.
+ * @return Id of registered listener.
+ */
+ int addRemoteDeviceSelectedListener(JSObjectRef callback, JSContextRef context);
+
+ /**
+ * Removes a listener previously registered by addRemoteDeviceSelectedListener().
+ * @param[in] id An id of registered listener to be removed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void removeRemoteDeviceSelectedListener(int id, JSContextRef context);
+
+ /**
+ * Dials a given phone number.
+ * @param[in] phoneNumber A phone number to dial.
+ * @param[in] errorCallback A callback to invoke when dialing has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void invokeCall(std::string phoneNumber, JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Answers incoming phone call.
+ * @param[in] errorCallback A callback to invoke when answering the call has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void answerCall(JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Declines incoming phone call, or hangs-up active one.
+ * @param[in] errorCallback A callback to invoke when hanging-up the call has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void hangupCall(JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Mutes/unmutes the active phone call.
+ * @param[in] mute Whether to mute, or unmute the active phone call.
+ * @param[in] errorCallback A callback to invoke when muting the call has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void muteCall(bool mute, JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Returns active phone call.
+ * @return Active phone call.
+ */
+ std::string activeCall(void);
+
+ /**
+ * Adds a listener to get notifified when there is a change on active call, ie. to get notified about incoming call and all other states that the call may go through, up to \b "disconnected" state.
+ * @param[in] callback A listener to call when there is a change on active call.
+ * @param[in] context A context on which the method is invoked.
+ * @return Id of registered listener.
+ */
+ int addCallChangedListener(JSObjectRef callback, JSContextRef context); // returns id of registered listener
+
+ /**
+ * Removes a listener previously registered by addCallChangedListener().
+ * @param[in] id An id of registered listener to be removed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void removeCallChangedListener(int id, JSContextRef context);
+
+ // Obex specific
+
+ /**
+ * Retrieves an array of \a \b count synchronized contacts in JSON \b tizen.Contact format.
+ * @param[in] count Specifies \a \b count the frist contacts to retrieve. \b 0 means to retrieve all contacts.
+ * @param[in] successCallback A callback to invoke when contacts are successfuly retrieved.
+ * @param[in] errorCallback A callback to invoke when retrieving the contacts has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void getContacts(unsigned long count, JSObjectRef successCallback, JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Retrieves an array of \a \b count synchronized call history entries in JSON \b tizen.CallHistoryEntry format.
+ * @param[in] count Specifies \a \b count the frist call history entries to retrieve.
+ * @param[in] successCallback A callback to invoke when call history entries are successfuly retrieved.
+ * @param[in] errorCallback A callback to invoke when retrieving the call history entries has failed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void getCallHistory(unsigned long count, JSObjectRef successCallback, JSObjectRef errorCallback, JSContextRef context);
+
+ /**
+ * Adds a listener to get notifified when a call entry has been added to the history list, due to incoming, or dialed call.
+ * @param[in] callback A listener to call when the call history entry was added to the list.
+ * @param[in] context A context on which the method is invoked.
+ * @return Id of registered listener.
+ */
+ int addCallHistoryEntryAddedListener(JSObjectRef callback, JSContextRef context);
+
+ /**
+ * Removes a listener previously registered by addCallHistoryEntryAddedListener().
+ * @param[in] id An id of registered listener to be removed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void removeCallHistoryEntryAddedListener(int id, JSContextRef context);
+
+ /**
+ * Adds a listener to get notifified when contacts list has changed, ie. when a new contact was added, or the list was cleared.
+ * @param[in] callback A listener to call when the contacts list has changed.
+ * @param[in] context A context on which the method is invoked.
+ * @return Id of registered listener.
+ */
+ int addContactsChangedListener(JSObjectRef callback, JSContextRef context);
+
+ /**
+ * Removes a listener previously registered by addContactsChangedListener().
+ * @param[in] id An id of registered listener to be removed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void removeContactsChangedListener(int id, JSContextRef context);
+
+ /**
+ * Adds a listener to get notifified when call history list has changed, ie. when a new call history entry was added, or the list was cleared.
+ * @param[in] callback A listener to call when the call history list has changed.
+ * @param[in] context A context on which the method is invoked.
+ * @return Id of registered listener.
+ */
+ int addCallHistoryChangedListener(JSObjectRef callback, JSContextRef context);
+
+ /**
+ * Removes a listener previously registered by addCallHistoryChangedListener().
+ * @param[in] id An id of registered listener to be removed.
+ * @param[in] context A context on which the method is invoked.
+ */
+ void removeCallHistoryChangedListener(int id, JSContextRef context);
+
+private:
+ // OFono specific
+ static void handleSignal( 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 asyncGetSelectedRemoteDeviceCB(GObject *source, GAsyncResult *result, gpointer user_data);
+
+private:
+ std::map<int, PhoneMaster::PhoneSubscriptionData*> mCallChangedListenersMap;
+ std::map<int, PhoneMaster::PhoneSubscriptionData*> mCallHistoryEntryAddedListenersMap;
+ std::map<int, PhoneMaster::PhoneSubscriptionData*> mContactsChangedListenersMap;
+ std::map<int, PhoneMaster::PhoneSubscriptionData*> mCallHistoryChangedListenersMap;
+ std::map<int, PhoneMaster::PhoneSubscriptionData*> mRemoteDeviceSelectedListenersMap;
+};
+
+/**
+ * A typedef for shared pointer to PhoneMaster.
+ */
+typedef DPL::SharedPtr<PhoneMaster> PhonePtr;
+
+
+} // Phone
+} // DeviceAPI
+
+#endif // PHONE_H
+
+/** @} */
+
--- /dev/null
+/**
+Details.
+\brief Allows access to the phone API
+*/
+
+module Phone {
+
+[NoInterfaceObject]
+interface PhoneError {
+ /** code
+ * MUST return error code.
+ **/
+ attribute unsigned short code;
+
+ /** message
+ * MUST return error message
+ **/
+ attribute DOMString message;
+};
+
+typedef DOMString PersonId;
+typedef DOMString ContactId;
+typedef DOMString ContactGroupId;
+
+[NoInterfaceObject]
+interface ContactName {
+ attribute DOMString? prefix;
+ attribute DOMString? suffix;
+ attribute DOMString? firstName;
+ attribute DOMString? middleName;
+ attribute DOMString? lastName;
+ attribute DOMString[] nicknames;
+ attribute DOMString? phoneticFirstName;
+ attribute DOMString? phoneticLastName;
+ readonly attribute DOMString? displayName;
+};
+
+[NoInterfaceObject]
+interface ContactAddress {
+ attribute DOMString? country;
+ attribute DOMString? region;
+ attribute DOMString? city;
+ attribute DOMString? streetAddress;
+ attribute DOMString? additionalInformation;
+ attribute DOMString? postalCode;
+ attribute boolean isDefault;
+ attribute DOMString[] types;
+};
+
+[NoInterfaceObject]
+interface ContactPhoneNumber {
+ attribute DOMString number;
+ attribute boolean isDefault;
+ attribute DOMString[] types;
+};
+
+[NoInterfaceObject]
+interface ContactEmailAddress {
+ attribute DOMString email;
+ attribute boolean isDefault;
+ attribute DOMString[] types;
+};
+
+[NoInterfaceObject]
+interface ContactAnniversary {
+ attribute Date date;
+ attribute DOMString? label;
+};
+
+[NoInterfaceObject]
+interface ContactOrganization {
+ attribute DOMString? name;
+ attribute DOMString? department;
+ attribute DOMString? title;
+ attribute DOMString? role;
+ attribute DOMString? logoURI;
+};
+
+[NoInterfaceObject]
+interface ContactWebSite {
+ attribute DOMString url;
+ attribute DOMString type;
+};
+
+[NoInterfaceObject]
+interface Contact {
+ readonly attribute ContactId? id;
+ readonly attribute PersonId? personId;
+ readonly attribute AddressBookId? addressBookId;
+ readonly attribute Date? lastUpdated;
+ readonly attribute boolean isFavorite;
+ attribute DOMString? photoURI;
+ attribute ContactPhoneNumber[] phoneNumbers;
+ attribute ContactEmailAddress[] emails;
+ attribute Date? birthday;
+ attribute ContactAnniversary[] anniversaries;
+ attribute ContactOrganization[] organizations;
+ attribute DOMString[] notes;
+ attribute ContactWebSite[] urls;
+ attribute DOMString? ringtoneURI;
+ attribute ContactGroupId[] groupIds;
+ //DOMString convertToString(optional ContactTextFormat? format);
+ //Contact clone();
+};
+
+[NoInterfaceObject]
+interface RemoteParty {
+ readonly attribute DOMString? remoteParty;
+ readonly attribute PersonId? personId;
+};
+
+[NoInterfaceObject]
+interface CallHistoryEntry {
+ readonly attribute DOMString uid;
+ readonly attribute DOMString type;
+ readonly attribute DOMString[]? features;
+ readonly attribute RemoteParty[] remoteParties;
+ readonly attribute Date startTime;
+ readonly attribute unsigned long duration;
+ readonly attribute DOMString direction;
+};
+
+callback PhoneErrorCallback = void (PhoneError error);
+callback GetContactsCallback = void (Contact[] contacts);
+callback GetCallHistoryCallback = void (CallHistoryEntry[] entries);
+
+[NoInterfaceObject]
+interface Phone {
+
+ /**
+ * \brief Invoke phone call on BT paired device
+ * \arg DOMString phoneNumber Phone number to invoke call to
+ * \arg PhoneErrorCallback errorCallback. Callback if an error has occurred
+ **/
+ invokeCall(DOMString phoneNumber, PhoneErrorCallback errorCallback);
+
+ /**
+ * \brief Answer incoming phone call.
+ * \arg PhoneErrorCallback errorCallback. Callback if an error has occurred
+ **/
+ answerCall(PhoneErrorCallback errorCallback);
+
+ /**
+ * \brief Hangup/End incoming/active phone call
+ * \arg PhoneErrorCallback errorCallback. Callback if an error has occurred
+ **/
+ hangupCall(PhoneErrorCallback errorCallback);
+
+ /**
+ * \brief Mute/UnMute active phone call on BT paired device
+ * \arg boolean mute Specifies whether the phone call should be muted, or unmuted.
+ **/
+ muteCall(boolean mute);
+
+ /**
+ * \brief Retrieve contacts from BT paired device
+ * \arg GetContactsCallback successCallback. Callback with the result of the method call
+ * \arg PhoneErrorCallback errorCallback. Callback if an error has occurred
+ **/
+ getContacts(GetContactsCallback successCallback, PhoneErrorCallback errorCallback);
+
+ /**
+ * \brief Get call history of given direction (DIALED/MISSED/RECEIVED)
+ * \arg DOMString direction An attribute to indicate the type of CallHistory to retrieve ("DIALED", "MISSED", "RECEIVED")
+ * \arg GetCallHistoryCallback successCallback. Callback with the result of the method call
+ * \arg PhoneErrorCallback errorCallback. Callback if an error has occurred
+ **/
+ getCallHistory(DOMString direction, GetCallHistoryCallback successCallback, PhoneErrorCallback errorCallback);
+};
+
+};
+
--- /dev/null
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+ <library-name>libwrt-plugins-tizen-phone.so</library-name>
+ <feature-install-uri>phone.install.uri</feature-install-uri>
+ <feature-key-cn>INTEL plugin group</feature-key-cn>
+ <feature-root-cn>INTEL certificate authority</feature-root-cn>
+ <feature-root-fingerprint>AAAABBBBCCCCDDDEEEE0000</feature-root-fingerprint>
+
+ <api-feature>
+ <name>http://tizen.org/privilege/phone</name>
+ <device-capability>phone</device-capability>
+ </api-feature>
+
+
+</plugin-properties>
--- /dev/null
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include "JSPhone.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Phone {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+class_definition_options_t ConstructorClassOptions =
+{
+ JS_INTERFACE,
+ CREATE_INSTANCE,
+ NONE_NOTICE,
+ USE_OVERLAYED,
+ NULL,
+ NULL,
+ NULL
+};
+
+void on_widget_start_callback(int widgetId) {
+ LoggerD("[TIZEN\\Phone] on_widget_start_callback ("<<widgetId<<")");
+ Try
+ {
+ WrtAccessSingleton::Instance().initialize(widgetId);
+ }
+ Catch(Commons::Exception)
+ {
+ LoggerE("WrtAccess initialization failed");
+ }
+}
+
+void on_widget_stop_callback(int widgetId) {
+ LoggerD("[TIZEN\\Phone] on_widget_stop_callback ("<<widgetId<<")");
+ Try
+ {
+ WrtAccessSingleton::Instance().deinitialize(widgetId);
+ }
+ Catch(Commons::Exception)
+ {
+ LoggerE("WrtAccess deinitialization failed");
+ }
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+ "phone",
+ (js_class_template_getter)JSPhone::getClassRef,
+ NULL)
+
+PLUGIN_CLASS_MAP_END
+
+} // Phone
+} // DeviceAPI
+
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
+