summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevron Rees <tripzero.kev@gmail.com>2014-11-05 17:29:07 -0800
committerKevron Rees <tripzero.kev@gmail.com>2014-11-05 17:29:07 -0800
commit687123b5f7fa7a4b172606583ad378452757b28b (patch)
tree83819285f1329172204636aee39c4adc8342908f
parent5051c66de77c5e939c141c90056120c694446696 (diff)
parent7f96771b09f0bc66c2d2c3a5a5c9cef9b2eea4c2 (diff)
downloadautomotive-message-broker-687123b5f7fa7a4b172606583ad378452757b28b.tar.gz
Merge pull request #28 from tripzero/master0.12.800
xwalk vehicle extension, fixes from 0.12 ported, more w3C vehicle data spec support.
-rw-r--r--CMakeLists.txt9
-rw-r--r--ambd/main.cpp20
-rw-r--r--docs/CMakeLists.txt3
-rw-r--r--docs/amb.idl201
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--examples/cangenconfig.in (renamed from examples/cangenconfig)6
-rw-r--r--examples/databasesource.in2
-rw-r--r--examples/opencvdbusconfig.in6
-rw-r--r--lib/abstractpropertytype.h16
-rw-r--r--lib/superptr.hpp10
-rw-r--r--lib/vehicleproperty.cpp141
-rw-r--r--lib/vehicleproperty.h83
-rw-r--r--plugins/bluemonkey/bluemonkey.cpp4
-rw-r--r--plugins/bluemonkey/bluemonkey.h6
-rw-r--r--plugins/cangenplugin/cangenplugin.cpp4
-rw-r--r--plugins/common/ambplugin.h4
-rw-r--r--plugins/database/databasesink.cpp11
-rw-r--r--plugins/database/databasesink.h3
-rw-r--r--plugins/dbus/automotivemanager.cpp8
-rw-r--r--plugins/dbus/dbusinterfacemanager.cpp6
-rw-r--r--plugins/dbus/environmentproperties.h2
-rw-r--r--plugins/dbus/runningstatus.h242
-rw-r--r--plugins/obd2plugin/obd2source.cpp64
-rw-r--r--plugins/opencvlux/CMakeLists.txt7
-rw-r--r--plugins/opencvlux/README42
-rw-r--r--plugins/opencvlux/opencvluxplugin.cpp158
-rw-r--r--plugins/opencvlux/opencvluxplugin.h19
-rw-r--r--xwalk/CMakeLists.txt23
-rw-r--r--xwalk/LICENSE27
-rw-r--r--xwalk/common/XW_Extension.h185
-rw-r--r--xwalk/common/XW_Extension_EntryPoints.h49
-rw-r--r--xwalk/common/XW_Extension_Permissions.h41
-rw-r--r--xwalk/common/XW_Extension_Runtime.h44
-rw-r--r--xwalk/common/XW_Extension_SyncMessage.h48
-rw-r--r--xwalk/common/extension.cc212
-rw-r--r--xwalk/common/extension.h96
-rw-r--r--xwalk/common/picojson.h1037
-rw-r--r--xwalk/common/utils.h22
-rw-r--r--xwalk/common/virtual_fs.cc317
-rw-r--r--xwalk/common/virtual_fs.h130
-rwxr-xr-xxwalk/generate_api.py19
-rw-r--r--xwalk/vehicle.cc711
-rw-r--r--xwalk/vehicle.h89
-rw-r--r--xwalk/vehicle.html61
-rw-r--r--xwalk/vehicle_api.cc2
-rw-r--r--xwalk/vehicle_api.js264
-rw-r--r--xwalk/vehicle_extension.cc29
-rw-r--r--xwalk/vehicle_extension.h20
-rw-r--r--xwalk/vehicle_instance.cc134
-rw-r--r--xwalk/vehicle_instance.h32
50 files changed, 4302 insertions, 368 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b29475e2..a91fcf0d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,9 +6,9 @@ set(CMAKE_BUILD_TYPE, Debug)
include(FindPkgConfig)
set(PROJECT_NAME "automotive-message-broker")
-set(PROJECT_VERSION "0.11.903")
-set(PROJECT_CODENAME "veyron")
-set(PROJECT_QUALITY "beta")
+set(PROJECT_VERSION "0.12.800")
+set(PROJECT_CODENAME "agera")
+set(PROJECT_QUALITY "alpha")
add_definitions(-DPROJECT_VERSION="${PROJECT_VERSION}")
add_definitions(-DPROJECT_NAME="${PROJECT_NAME}")
@@ -40,6 +40,8 @@ option(cangen_plugin "Can generator plugin" OFF)
option(enable_icecc "Enable icecc checking, for distributed compilation" ON)
option(enable_docs "enable Doxygen doc generation" OFF)
option(usebluez5 "use bluez 5 API" OFF)
+option(xwalk_vehicle_extension "Crosswalk vehicle extension" OFF)
+set(XWALK_EXTENSION_PATH "/automotive-message-broker/xwalk" CACHE PATH "directory the xwalk extension will be installed to")
#turn on -fpic/-fpie:
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@@ -151,3 +153,4 @@ add_subdirectory(plugins)
add_subdirectory(docs)
add_subdirectory(tests)
add_subdirectory(examples)
+add_subdirectory(xwalk)
diff --git a/ambd/main.cpp b/ambd/main.cpp
index 5c6bb9d1..6d91e5b0 100644
--- a/ambd/main.cpp
+++ b/ambd/main.cpp
@@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <QCoreApplication>
-#else
+#else
#include <glib.h>
@@ -54,7 +54,7 @@ void interrupt(int sign)
{
signal(sign, SIG_IGN);
cout<<"Signal caught. Exiting gracefully.\n"<<endl;
-
+
/// this will cause the application to terminate and clean up:
delete mainloop;
}
@@ -83,7 +83,7 @@ void printVersion()
DebugOut(0)<<"Version: "<<PROJECT_VERSION<<" ( "<<PROJECT_CODENAME<<" "<<PROJECT_QUALITY<<" )"<<endl;
}
-int main(int argc, char **argv)
+int main(int argc, char **argv)
{
bool isdeamonize=false;
@@ -100,7 +100,7 @@ int main(int argc, char **argv)
case 'D':
isdeamonize = true;
break;
-
+
case 'v':
printVersion();
return (0);
@@ -129,10 +129,10 @@ int main(int argc, char **argv)
break;
}
}
-
+
if(isdeamonize)
daemonize();
-
+
if(!logfn.empty())
{
logfile.open(logfn, ios::out | ios::trunc);
@@ -151,14 +151,14 @@ int main(int argc, char **argv)
#endif
VehicleProperty::factory();
-
+
PluginLoader loader(config, argc, argv);
-
+
if(!loader.sources().size())
{
throw std::runtime_error("No sources present. aborting");
}
-
+
mainloop = loader.mainloop();
/* Register signal handler */
@@ -166,8 +166,6 @@ int main(int argc, char **argv)
signal(SIGTERM, interrupt);
mainloop->exec();
-
- VehicleProperty::shutdown();
if(logfile.is_open())
logfile.close();
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 4a2af488..69e99af3 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -3,4 +3,7 @@ if(enable_docs)
install (DIRECTORY dbus DESTINATION ${DOC_INSTALL_DIR} COMPONENT Docs)
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/amb.idl DESTINATION ${DOC_INSTALL_DIR}/dbus/html/ COMPONENT Docs)
add_custom_target(doc_idl ALL mkdir -p ${CMAKE_CURRENT_SOURCE_DIR}/dbus/html/ && cp ${CMAKE_CURRENT_SOURCE_DIR}/amb.idl ${CMAKE_CURRENT_SOURCE_DIR}/dbus/html/amb.idl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Moving amb.idl" VERBATIM)
+
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb.idl ${CMAKE_CURRENT_SOURCE_DIR}/amb.idl @ONLY)
+
endif(enable_docs)
diff --git a/docs/amb.idl b/docs/amb.idl
index 35a7cc5f..941ae7eb 100644
--- a/docs/amb.idl
+++ b/docs/amb.idl
@@ -110,7 +110,9 @@ interface org.automotive.Manager {
* except that it takes an addition zone argument and only returns the path for that zone.
* \arg String property is the requested property to be retrieved.
* \arg Zone zone is the zone which the object
- * \returns string representing the DBus Object path
+ * \returns string representing the DBus Object path. Possible errors:
+ * "org.automotive.Manager.InvalidZone"
+ * "org.automotive.Manager.ObjectNotFound"
*/
method FindObjectForZone {
in {
@@ -197,19 +199,19 @@ interface org.automotive.TripMeter extends VehiclePropertyType {
interface org.automotive.Acceleration extends VehiclePropertyType {
/*! X
- * \brief Must return acceleration on the "X" axis as 1/1000 G (gravitational force).
+ * \brief return acceleration on the "X" axis (Unit: centimeters per second squared)
*/
- attribute UInt16 X readonly
+ attribute Int16 X readonly
/*! Y
- * \brief Must return acceleration on the "Y" axis as 1/1000 G (gravitational force).
+ * \brief return acceleration on the "Y" axis (Unit: centimeters per second squared)
*/
- attribute UInt16 Y readonly
+ attribute Int16 Y readonly
/*! Z
- * \brief Must return acceleration on the "Z" axis as 1/1000 G (gravitational force).
+ * \brief return acceleration on the "Z" axis (Unit: centimeters per second squared)
*/
- attribute UInt16 Z readonly
+ attribute Int16 Z readonly
}
enumeration TransmissionMode {
@@ -222,7 +224,7 @@ enumeration TransmissionMode {
}
/*! TransmissionPosition
- * \brief Describes Transmission Pistion. Deprecated. Will disappear in 0.13
+ * \brief Describes Transmission Pistion. Deprecated. Will disappear in 0.14
*/
enumeration TransmissionPosition {
Neutral = 0,
@@ -278,7 +280,7 @@ interface org.automotive.Transmission extends VehiclePropertyType {
interface org.automotive.CruiseControlStatus extends VehiclePropertyType {
/*! Activated
- * \brief Must return whether or not the Cruise Control system is active (true) or inactive (false)
+ * \brief Must return whether or not the Cruise Control system is active (true) or inactive (false). Depricated. Remove in 0.14. Use "Status"
*/
attribute Boolean Activated readonly
@@ -286,10 +288,15 @@ interface org.automotive.CruiseControlStatus extends VehiclePropertyType {
* \brief Must return target Cruise Control speed in kilometers per hour (kph).
*/
attribute UInt16 Speed readonly
+
+ /*! Status
+ * \brief Must return whether or not the Cruise Control system is active (true) or inactive (false).
+ */
+ attribute Boolean Status readonly
}
/*!
- * Deprecated. Use BrakeOperation. Remove in 0.13
+ * Deprecated. Use BrakeOperation. Remove in 0.14
*/
interface org.automotive.WheelBrake extends VehiclePropertyType {
@@ -312,71 +319,76 @@ interface org.automotive.LightStatus extends VehiclePropertyType {
/*! Head
* \brief Must return headlight status: on = true, off = false.
*/
- attribute Boolean Head readonly
+ attribute Boolean Head
/*! RightTurn
* \brief Must return right turn signal status: on = true, off = false.
*/
- attribute Boolean RightTurn readonly
+ attribute Boolean RightTurn
/*! LeftTurn
* \brief Must return left turn signal status: on = true, off = false.
*/
- attribute Boolean LeftTurn readonly
+ attribute Boolean LeftTurn
/*! Brake
* \brief Must return brake signal light status: on = true, off = false.
*/
- attribute Boolean Brake readonly
+ attribute Boolean Brake
/*! Fog
* \brief Must return fog light status: on = true, off = false.
*/
- attribute Boolean Fog readonly
+ attribute Boolean Fog
/*! Hazard
* \brief Must return hazard light status: on = true, off = false.
*/
- attribute Boolean Hazard readonly
+ attribute Boolean Hazard
/*! Parking
* \brief Must return parking light status: on = true, off = false.
*/
- attribute Boolean Parking readonly
+ attribute Boolean Parking
/*! HighBeam
* \brief Must return high beam status: on = true, off = false.
*/
- attribute Boolean HighBeam readonly
+ attribute Boolean HighBeam
/*! AutomaticHeadlights
* \brief Must return automatic headlight status: on = true, off = false.
*/
- attribute Boolean AutomaticHeadlights readonly
+ attribute Boolean AutomaticHeadlights
/*! DynamicHighBeam
* \brief Must return dynamic high beam status: on = true, off = false.
*/
- attribute Boolean DynamicHighBeam readonly
+ attribute Boolean DynamicHighBeam
}
interface org.automotive.InteriorLightStatus extends VehiclePropertyType {
/*! Passenger
- * \brief Must return passenger interior light status: on = true, off = false
+ * \brief Must return passenger interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
*/
attribute Boolean Passenger readonly
/*! Driver
- * \brief Must return driver interior light status: on = true, off = false
+ * \brief Must return driver interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
*/
attribute Boolean Driver readonly
/*! Center
- * \brief Must return center interior light status: on = true, off = false
+ * \brief Must return center interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
*/
attribute Boolean Center readonly
+
+ /*! Status
+ * \brief Must return interior light status for the zone. on = true, off = false
+ */
+ attribute Boolean Status
}
@@ -426,29 +438,45 @@ interface org.automotive.Fuel extends VehiclePropertyType {
*/
attribute UInt32 FuelConsumedSinceRestart readonly;
- /*! FuelConsumedSinceRestart
- * \brief must return fuel consumed since engine start; (Unit: milliliters per 100 kilometers) resets to 0 each restart
+ /*! TimeSinceRestart
+ * \brief must return time elapsed since vehicle restart (Unit: seconds)
*/
- attribute UInt32 FuelConsumedSinceRestart readonly;
+ attribute UInt32 TimeSinceRestart readonly;
}
interface org.automotive.EngineOil extends VehiclePropertyType {
/*! Remaining
- * \brief Must return remaining engine oil as percentage of fullness.
+ * \brief Must return remaining engine oil as percentage of fullness. Deprecated. Remove in 0.14. Use "Level"
*/
attribute UInt16 Remaining readonly
/*! Temperature
- * \brief Must return Engine Oil Temperature in Celcius.
+ * \brief Must return Engine Oil Temperature in Celcius.
*/
attribute long Temperature readonly
/*! Pressure
- * \brief Must return Engine Oil Pressure in kPa.
+ * \brief Must return Engine Oil Pressure in kPa.
*/
attribute UInt16 Pressure readonly
+
+ /*! Level
+ * \brief Must return engine oil level (Unit: percentage, 0%: empty, 100%: full
+ */
+ attribute UInt16 Level readonly
+
+ /*! Change
+ * \brief Must return engine oil change indicator status: change oil (true) or no change (false)
+ */
+ attribute boolean Change readonly
+
+ /*! LifeRemaining
+ * \brief Must return engine oil change indicator status: change oil (true) or no change (false)
+ */
+ attribute boolean LifeRemaining readonly
+
}
@@ -490,13 +518,13 @@ interface org.automotive.Temperature extends VehiclePropertyType {
/*! Interior
* \brief Must return the temperature of the interior of the vehicle in celcius.
*/
- /// Deprecated. Use InteriorTemperature. Remove in 0.13
+ /// Deprecated. Use InteriorTemperature. Remove in 0.14
attribute signed short Interior readonly
/*! Exterior
* \brief Must return the temperature of the exterior of the vehicle in celcius.
*/
- /// Deprecated. Use ExteriorTemperature. Remove in 0.13
+ /// Deprecated. Use ExteriorTemperature. Remove in 0.14
attribute signed short Exterior readonly
/*! Interior
@@ -532,7 +560,7 @@ interface org.automotive.WindshieldWiper extends VehiclePropertyType {
attribute UInt16 WindshieldWiper readonly
}
-/*! Deprecated. Use ClimateControl interface. Remove in 0.13
+/*! Deprecated. Use ClimateControl interface. Remove in 0.14
*/
interface org.automotive.HVAC extends VehiclePropertyType {
const UInt16 AIRFLOWDIRECTION_FRONTPANEL = 0;
@@ -651,7 +679,7 @@ interface org.automotive.WindowStatus extends VehiclePropertyType {
/*! Defrost
* \brief Must return the defroster status of the window. On = true, Off = false.
- * Deprecated. Use Defrost interface. Remove in 0.13.
+ * Deprecated. Use Defrost interface. Remove in 0.14.
*/
attribute Boolean Defrost;
}
@@ -807,7 +835,7 @@ interface org.automotive.Odometer extends VehiclePropertyType {
/*! Odometer
* \brief MUST return Distance traveled in km
*/
- /// Deprecated. Use DistanceTotal. Remove in 0.13
+ /// Deprecated. Use DistanceTotal. Remove in 0.14
attribute UInt32 Odometer readonly
/*! DistnaceTotal
@@ -841,7 +869,7 @@ interface org.automotive.Fluid extends VehiclePropertyType {
attribute UInt16 Washer readonly
}
-/// Deprecated. Use BatteryStatus. Remove in 0.13
+/// Deprecated. Use BatteryStatus. Remove in 0.14
interface org.automotive.Battery extends VehiclePropertyType {
/*! Voltage
@@ -901,7 +929,7 @@ interface org.automotive.SecurityAlert extends VehiclePropertyType {
attribute Boolean SecurityAlert readonly
}
-/// Deprecated. Use LightStatus. remove in 0.13
+/// Deprecated. Use LightStatus. remove in 0.14
interface org.automotive.ParkingBrake extends VehiclePropertyType {
/*! ParkingBrake
@@ -910,7 +938,7 @@ interface org.automotive.ParkingBrake extends VehiclePropertyType {
attribute Boolean ParkingBrake readonly
}
-/// Deprecated. Use LightStatus. remove in 0.13
+/// Deprecated. Use LightStatus. remove in 0.14
interface org.automotive.ParkingLight extends VehiclePropertyType {
/*! ParkingLight
@@ -919,7 +947,7 @@ interface org.automotive.ParkingLight extends VehiclePropertyType {
attribute Boolean ParkingLight readonly
}
-/// Deprecated. Use LightStatus. remove in 0.13
+/// Deprecated. Use LightStatus. remove in 0.14
interface org.automotive.HazardLight extends VehiclePropertyType {
/*! HazardLight
@@ -975,7 +1003,7 @@ enumeration AirbagStatus {
}
/*!
- * Deprecated. Use "Door". Remove in 0.13
+ * Deprecated. Use "Door". Remove in 0.14
*/
interface org.automotive.DoorStatus extends VehiclePropertyType {
@@ -1060,7 +1088,7 @@ interface org.automotive.NightMode extends VehiclePropertyType {
/*!
* \brief MUST return whether or not the system is in NightMode or not. True = Night time, False = Day time
- * Deprecated. Will be removed in 0.13. Use "Mode"
+ * Deprecated. Will be removed in 0.14. Use "Mode"
*/
attribute Boolean NightMode readonly
@@ -1253,12 +1281,101 @@ interface org.automotive.EngineCoolant extends VehiclePropertyType {
/*!
* \brief MUST return engine coolant level (Unit: percentage 0%: empty, 100%: full)
*/
- attribute Uint8 Level readonly
+ attribute Uint16 Level readonly
/*!
* \brief MUST return engine coolant temperature (Unit: celcius)
*/
- attribute Uint8 Temperature readonly
+ attribute Int16 Temperature readonly
+}
+
+interface org.automotive.PowertrainTorque extends VehiclePropertyType {
+
+ /*!
+ * \brief must return powertrain torque (Unit: newton meters)
+ */
+ attribute UInt16 Value readonly
+}
+
+interface org.automotive.AcceleratorPedalPosition extends VehiclePropertyType {
+
+ /*!
+ * \brief must return accelerator pedal position as a percentage (Unit: percentage, 0%: released pedal, 100%: fully depressed)
+ */
+ attribute UInt8 Value readonly
+}
+
+interface org.automotive.WheelTick extends VehiclePropertyType {
+
+ /*!
+ * \brief must return number of ticks per second (Unit: ticks per second)
+ */
+ attribute UInt8 Value readonly
+}
+
+interface IgnitionTime : VehicleCommonDataType {
+ /*!
+ * \brief must return time at ignition on
+ */
+ attribute UInt64 ignitionOnTime readonly
+
+ /*!
+ * \brief must return time at ignition off
+ */
+ attribute UInt64 ignitionOffTime readonly
+};
+
+interface org.automotive.YawRate extends VehiclePropertyType {
+
+ /*!
+ * \brief must return yaw rate of vehicle. (Unit: degrees per second)
+ */
+ attribute Int16 Value readonly
+}
+
+interface org.automotive.BrakeOperation extends VehiclePropertyType {
+
+ /*!
+ * \brief must return whether brake pedal is depressed or not. true: brake pedal is depressed, false: brake pedal is not depressed
+ */
+ attribute Boolean BrakePedalDepressed readonly
+}
+
+enum VehicleButton {
+ home = "home",
+ back = "back",
+ search = "search",
+ call = "call",
+ end_call = "end_call",
+ media_play = "media_play",
+ media_next = "media_next",
+ media_previous = "media_previous",
+ media_pause = "media_pause",
+ voice_recognize = "voice_recognize",
+ enter = "enter",
+ left = "left",
+ right = "right",
+ up = "up",
+ down = "down"
+}
+
+enum PressType {
+ press = "press",
+ long_press = "long_press",
+ release = "release"
+};
+
+interface org.automotive.ButtonEvent extends VehiclePropertyType {
+
+ /*!
+ * \brief must return the button events tha occured. This supports multiple simultanious button events.
+ */
+ attribute array Button of VehicleButton readonly
+
+ /*!
+ * \brief must return the type of event
+ */
+ attribute PressType State readonly
}
}
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 4d68156a..28ff5a33 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -16,6 +16,7 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/qtmainloopconfig.in ${CMAKE_CURRENT_
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsink2.in ${CMAKE_CURRENT_SOURCE_DIR}/websocketsink2 @ONLY)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsource2.in ${CMAKE_CURRENT_SOURCE_DIR}/websocketsource2 @ONLY)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/testsourceconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/testsourceconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cangenconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/cangenconfig @ONLY)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey/bluemonkeyconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey/bluemonkeyconfig @ONLY)
install (FILES ${amb_examples} DESTINATION /etc/ambd/examples)
diff --git a/examples/cangenconfig b/examples/cangenconfig.in
index 816c74e6..81add2cb 100644
--- a/examples/cangenconfig
+++ b/examples/cangenconfig.in
@@ -2,18 +2,18 @@
"sources" : [
{
"name" : "CANSimPlugin",
- "path":"/usr/lib/automotive-message-broker/cansimplugin.so",
+ "path":"@PLUGIN_INSTALL_PATH@/cansimplugin.so",
"interfaces" : ["vcan0", "vcan1"]
},
{
"name" : "CANGenPlugin",
- "path":"/usr/lib/automotive-message-broker/cangenplugin.so"
+ "path":"@PLUGIN_INSTALL_PATH@/cangenplugin.so"
}
],
"sinks": [
{
"name" : "DBusSink",
- "path" : "/usr/lib/automotive-message-broker/dbussinkplugin.so",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
"frequency" : "60"
}
diff --git a/examples/databasesource.in b/examples/databasesource.in
index ccfa4915..69ab8cb9 100644
--- a/examples/databasesource.in
+++ b/examples/databasesource.in
@@ -4,7 +4,7 @@
"name" : "Database Source",
"path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
"playbackOnLoad" : "true",
- "databaseFile" : "generated.db"
+ "databaseFile" : "/tmp/storage"
}
],
"sinks": [
diff --git a/examples/opencvdbusconfig.in b/examples/opencvdbusconfig.in
index 0ee79402..a3743987 100644
--- a/examples/opencvdbusconfig.in
+++ b/examples/opencvdbusconfig.in
@@ -5,14 +5,16 @@
"name" : "OpenCV LUX",
"path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
"threaded" : "true",
- "cuda" : "true",
+ "cuda" : "false",
+ "opencl" : "true",
"fps" : "30",
"pixelLowerBound" : "18",
"pixelUpperBound" : "255",
"device" : "0",
"codec" : "divx",
"logging" : "true",
- "logfile" : "/tmp/video.avi"
+ "logfile" : "/tmp/video.avi",
+ "ddd" : "true"
},
{
"path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
diff --git a/lib/abstractpropertytype.h b/lib/abstractpropertytype.h
index c13cb41d..5b7128e0 100644
--- a/lib/abstractpropertytype.h
+++ b/lib/abstractpropertytype.h
@@ -291,6 +291,22 @@ public:
};
template <>
+class GVS<uint8_t>
+{
+public:
+ static const char* signature() { return "q"; }
+
+ static uint16_t value(GVariant* v)
+ {
+ return g_variant_get_uint16(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
class GVS<uint16_t>
{
public:
diff --git a/lib/superptr.hpp b/lib/superptr.hpp
index 26e90878..c91a2c2f 100644
--- a/lib/superptr.hpp
+++ b/lib/superptr.hpp
@@ -60,6 +60,16 @@ struct traits<gchar> {
};
};
+template <>
+struct traits<GDBusConnection> {
+ struct delete_functor {
+ void operator()(GDBusConnection* p) const {
+ if (p != nullptr)
+ g_dbus_connection_close_sync(p, nullptr, nullptr);
+ }
+ };
+};
+
template<typename T> using super_ptr =
::std::unique_ptr<T, typename traits<T>::delete_functor>;
diff --git a/lib/vehicleproperty.cpp b/lib/vehicleproperty.cpp
index 3573ce28..d4cd94c9 100644
--- a/lib/vehicleproperty.cpp
+++ b/lib/vehicleproperty.cpp
@@ -21,6 +21,7 @@
#include "listplusplus.h"
#include "debugout.h"
#include "mappropertytype.hpp"
+#include "superptr.hpp"
#include <map>
@@ -34,7 +35,23 @@ using namespace std;
std::map<VehicleProperty::Property, VehicleProperty::PropertyTypeFactoryCallback> VehicleProperty::registeredPropertyFactoryMap;
-VehicleProperty* VehicleProperty::thereCanOnlyBeOne = nullptr;
+std::unique_ptr<VehicleProperty> VehicleProperty::thereCanOnlyBeOne(nullptr);
+
+const char* ButtonEvents::W3C::Home = "home";
+const char* ButtonEvents::W3C::Back = "back";
+const char* ButtonEvents::W3C::Search = "search";
+const char* ButtonEvents::W3C::Call = "call";
+const char* ButtonEvents::W3C::EndCall = "end_call";
+const char* ButtonEvents::W3C::MediaPlay = "media_play";
+const char* ButtonEvents::W3C::MediaPause = "media_pause";
+const char* ButtonEvents::W3C::MediaPrevious = "media_previous";
+const char* ButtonEvents::W3C::MediaNext = "media_next";
+const char* ButtonEvents::W3C::VoiceRecognize = "voice_regocnize";
+const char* ButtonEvents::W3C::Enter = "enter";
+const char* ButtonEvents::W3C::Left = "left";
+const char* ButtonEvents::W3C::Right = "right";
+const char* ButtonEvents::W3C::Up = "up";
+const char* ButtonEvents::W3C::Down = "down";
const char* Transmission::W3C::Park = "park";
const char* Transmission::W3C::Reverse = "reverse";
@@ -82,6 +99,8 @@ const VehicleProperty::Property VehicleProperty::BatteryChargeLevel = "BatteryCh
const VehicleProperty::Property VehicleProperty::InteriorTemperature = "InteriorTemperature";
const VehicleProperty::Property VehicleProperty::ExteriorTemperature = "ExteriorTemperature";
const VehicleProperty::Property VehicleProperty::EngineOilTemperature = "EngineOilTemperature";
+const VehicleProperty::Property VehicleProperty::EngineOilLifeRemaining = "EngineOilLifeRemaining";
+const VehicleProperty::Property VehicleProperty::EngineOilChangeIndicator= "EngineOilChangeIndicator";
const VehicleProperty::Property VehicleProperty::VIN = "VIN";
const VehicleProperty::Property VehicleProperty::WMI = "WMI";
const VehicleProperty::Property VehicleProperty::TirePressure = "TirePressure";
@@ -104,6 +123,7 @@ const VehicleProperty::Property VehicleProperty::LightDynamicHighBeam= "LightDyn
const VehicleProperty::Property VehicleProperty::InteriorLightDriver = "InteriorLightDriver";
const VehicleProperty::Property VehicleProperty::InteriorLightCenter = "InteriorLightCenter";
const VehicleProperty::Property VehicleProperty::InteriorLightPassenger = "InteriorLightPassenger";
+const VehicleProperty::Property VehicleProperty::InteriorLightStatus = "InteriorLightStatus";
const VehicleProperty::Property VehicleProperty::EngineLoad = "EngineLoad";
const VehicleProperty::Property VehicleProperty::Horn = "Horn";
const VehicleProperty::Property VehicleProperty::FuelLevel = "FuelLevel";
@@ -192,6 +212,14 @@ const VehicleProperty::Property VehicleProperty::SeatPositionSideCushion = "Seat
const VehicleProperty::Property VehicleProperty::DashboardIllumination = "DashboardIllumination";
const VehicleProperty::Property VehicleProperty::GeneratedVehicleSoundMode = "GeneratedVehicleSoundMode";
const VehicleProperty::Property VehicleProperty::DriverId = "DriverId";
+const VehicleProperty::Property VehicleProperty::PowertrainTorque = "PowertrainTorque";
+const VehicleProperty::Property VehicleProperty::AcceleratorPedalPosition = "AcceleratorPedalPosition";
+const VehicleProperty::Property VehicleProperty::Chime = "Chime";
+const VehicleProperty::Property VehicleProperty::WheelTick = "WheelTick";
+const VehicleProperty::Property VehicleProperty::IgnitionTimeOn = "IgnitionTimeOn";
+const VehicleProperty::Property VehicleProperty::IgnitionTimeOff = "IgnitionTimeOff";
+const VehicleProperty::Property VehicleProperty::YawRate = "YawRate";
+const VehicleProperty::Property VehicleProperty::ButtonEventW3C = "ButtonEventW3C";
PropertyList VehicleProperty::mCapabilities;
PropertyList VehicleProperty::mCustomProperties;
@@ -200,41 +228,43 @@ VehicleProperty::VehicleProperty()
{
REGISTERPROPERTY( VehicleSpeed, 0);
REGISTERPROPERTY(EngineSpeed, 0);
- REGISTERPROPERTY(TransmissionShiftPosition,Transmission::Neutral);
- REGISTERPROPERTY(TransmissionGearPosition,Transmission::Neutral);
- REGISTERPROPERTY(TransmissionMode,Transmission::Normal);
- REGISTERPROPERTY(TransmissionModeW3C,"neutral");
+ REGISTERPROPERTY(TransmissionShiftPosition, Transmission::Neutral);
+ REGISTERPROPERTY(TransmissionGearPosition, Transmission::Neutral);
+ REGISTERPROPERTY(TransmissionMode, Transmission::Normal);
+ REGISTERPROPERTY(TransmissionModeW3C, "neutral");
REGISTERPROPERTY(ThrottlePosition, 0);
REGISTERPROPERTY(WheelBrake, false);
- REGISTERPROPERTY(WheelBrakePressure,0);
- REGISTERPROPERTY(SteeringWheelAngle,0);
- REGISTERPROPERTY(SteeringWheelAngleW3C,0);
+ REGISTERPROPERTY(WheelBrakePressure, 0);
+ REGISTERPROPERTY(SteeringWheelAngle, 0);
+ REGISTERPROPERTY(SteeringWheelAngleW3C, 0);
REGISTERPROPERTY(TurnSignal, TurnSignals::Off);
REGISTERPROPERTY(ClutchStatus, false);
REGISTERPROPERTY(EngineOilPressure, 0);
REGISTERPROPERTY(EngineOilTemperature, 0);
- REGISTERPROPERTY(EngineOilRemaining,0);
+ REGISTERPROPERTY(EngineOilRemaining, 0);
+ REGISTERPROPERTY(EngineOilLifeRemaining, 0);
+ REGISTERPROPERTY(EngineOilChangeIndicator, false);
REGISTERPROPERTY(EngineCoolantTemperature, 0);
REGISTERPROPERTY(EngineCoolantLevel, 0);
REGISTERPROPERTY(MachineGunTurretStatus, false);
- REGISTERPROPERTY(AccelerationX,0);
- REGISTERPROPERTY(AccelerationY,0);
- REGISTERPROPERTY(AccelerationZ,0);
- REGISTERPROPERTY(MassAirFlow,0);
+ REGISTERPROPERTY(AccelerationX, 0);
+ REGISTERPROPERTY(AccelerationY, 0);
+ REGISTERPROPERTY(AccelerationZ, 0);
+ REGISTERPROPERTY(MassAirFlow, 0);
REGISTERPROPERTY(ButtonEvent, ButtonEvents::NoButton);
- REGISTERPROPERTY(AirIntakeTemperature,0)
+ REGISTERPROPERTY(AirIntakeTemperature, 0)
REGISTERPROPERTY(BatteryVoltage, 0);
- REGISTERPROPERTY(BatteryCurrent,0);
- REGISTERPROPERTY(BatteryChargeLevel,0);
+ REGISTERPROPERTY(BatteryCurrent, 0);
+ REGISTERPROPERTY(BatteryChargeLevel, 0);
REGISTERPROPERTY(InteriorTemperature, 0);
- REGISTERPROPERTY(ExteriorTemperature,0);
+ REGISTERPROPERTY(ExteriorTemperature, 0);
REGISTERPROPERTY(VIN, "");
REGISTERPROPERTY(WMI, "");
REGISTERPROPERTY(TirePressure, 0);
REGISTERPROPERTY(TirePressureLow, false);
- REGISTERPROPERTY(TireTemperature,0);
- REGISTERPROPERTY( VehiclePowerMode,Power::Off);
- registerPropertyPriv(TripMeters,[](){
+ REGISTERPROPERTY(TireTemperature, 0);
+ REGISTERPROPERTY( VehiclePowerMode, Power::Off);
+ registerPropertyPriv(TripMeters, [](){
TripMetersType* t = new TripMetersType();
BasicPropertyType<uint16_t> v(0);
t->append(&v);
@@ -242,7 +272,7 @@ VehicleProperty::VehicleProperty()
});
REGISTERPROPERTY(CruiseControlActive, false);
- REGISTERPROPERTY(CruiseControlSpeed,0);
+ REGISTERPROPERTY(CruiseControlSpeed, 0);
REGISTERPROPERTY(LightHead, false);
REGISTERPROPERTY(LightLeftTurn, false);
REGISTERPROPERTY(LightRightTurn, false);
@@ -256,6 +286,7 @@ VehicleProperty::VehicleProperty()
REGISTERPROPERTY(InteriorLightDriver, false);
REGISTERPROPERTY(InteriorLightPassenger, false);
REGISTERPROPERTY(InteriorLightCenter, false);
+ REGISTERPROPERTY(InteriorLightStatus, false);
REGISTERPROPERTY(EngineLoad, 0);
REGISTERPROPERTY(Horn, false);
REGISTERPROPERTY(FuelLevel, 0);
@@ -274,7 +305,7 @@ VehicleProperty::VehicleProperty()
REGISTERPROPERTY(VehicleLength, 0);
REGISTERPROPERTY(Latitude, 0);
REGISTERPROPERTY(Longitude, 0);
- REGISTERPROPERTY(Altitude,0);
+ REGISTERPROPERTY(Altitude, 0);
REGISTERPROPERTY(Direction, 0);
REGISTERPROPERTY(VehicleType, Vehicle::Unknown);
registerPropertyPriv(DoorsPerRow, []() { BasicPropertyType<uint16_t> d(0); return new DoorsPerRowType(&d); });
@@ -286,10 +317,10 @@ VehicleProperty::VehicleProperty()
REGISTERPROPERTY(Odometer, 0);
REGISTERPROPERTY(DistanceTotal, 0);
REGISTERPROPERTY(DistanceSinceStart, 0);
- REGISTERPROPERTY(TransmissionFluidLevel,0);
- REGISTERPROPERTY(BrakeFluidLevel,0);
- REGISTERPROPERTY(WasherFluidLevel,0);
- REGISTERPROPERTY(SecurityAlertStatus,Security::Idle);
+ REGISTERPROPERTY(TransmissionFluidLevel, 0);
+ REGISTERPROPERTY(BrakeFluidLevel, 0);
+ REGISTERPROPERTY(WasherFluidLevel, 0);
+ REGISTERPROPERTY(SecurityAlertStatus, Security::Idle);
REGISTERPROPERTY(ParkingBrakeStatus, false);
REGISTERPROPERTY(ParkingLightStatus, false);
REGISTERPROPERTY(HazardLightStatus, false);
@@ -318,11 +349,11 @@ VehicleProperty::VehicleProperty()
REGISTERPROPERTY(AirRecirculation, false);
REGISTERPROPERTY(Heater, false);
- REGISTERPROPERTY(Defrost,false);
- REGISTERPROPERTY(DefrostWindow,false);
- REGISTERPROPERTY(DefrostMirror,false);
+ REGISTERPROPERTY(Defrost, false);
+ REGISTERPROPERTY(DefrostWindow, false);
+ REGISTERPROPERTY(DefrostMirror, false);
- REGISTERPROPERTY(SteeringWheelHeater,false);
+ REGISTERPROPERTY(SteeringWheelHeater, false);
REGISTERPROPERTY(SeatHeater, 0);
REGISTERPROPERTY(SeatCooler, false);
REGISTERPROPERTY(WindowStatus, 100);
@@ -332,40 +363,36 @@ VehicleProperty::VehicleProperty()
REGISTERPROPERTY(NightMode, false);
REGISTERPROPERTY(DrivingMode, Driving::None);
REGISTERPROPERTY(DrivingModeW3C, false);
- REGISTERPROPERTY(KeyId,"");
- REGISTERPROPERTY(Language,"");
- REGISTERPROPERTY(MeasurementSystem,Measurement::Metric);
- REGISTERPROPERTY(MirrorSettingPan,0);
- REGISTERPROPERTY(MirrorSettingTilt,0);
- REGISTERPROPERTY(SteeringWheelPositionSlide,0);
- REGISTERPROPERTY(SteeringWheelPositionTilt,0);
- REGISTERPROPERTY(SeatPositionRecline,0);
- REGISTERPROPERTY(SeatPositionSlide,0);
- REGISTERPROPERTY(SeatPositionCushionHeight,0);
- REGISTERPROPERTY(SeatPositionHeadrest,0);
- REGISTERPROPERTY(SeatPositionBackCushion,0);
- REGISTERPROPERTY(SeatPositionSideCushion,0);
- REGISTERPROPERTY(DashboardIllumination,0);
+ REGISTERPROPERTY(KeyId, "");
+ REGISTERPROPERTY(Language, "");
+ REGISTERPROPERTY(MeasurementSystem, Measurement::Metric);
+ REGISTERPROPERTY(MirrorSettingPan, 0);
+ REGISTERPROPERTY(MirrorSettingTilt, 0);
+ REGISTERPROPERTY(SteeringWheelPositionSlide, 0);
+ REGISTERPROPERTY(SteeringWheelPositionTilt, 0);
+ REGISTERPROPERTY(SeatPositionRecline, 0);
+ REGISTERPROPERTY(SeatPositionSlide, 0);
+ REGISTERPROPERTY(SeatPositionCushionHeight, 0);
+ REGISTERPROPERTY(SeatPositionHeadrest, 0);
+ REGISTERPROPERTY(SeatPositionBackCushion, 0);
+ REGISTERPROPERTY(SeatPositionSideCushion, 0);
+ REGISTERPROPERTY(DashboardIllumination, 0);
REGISTERPROPERTY(GeneratedVehicleSoundMode, Vehicle::Normal);
REGISTERPROPERTY(DriverId, "");
-
+ REGISTERPROPERTY(PowertrainTorque, 0);
+ REGISTERPROPERTY(AcceleratorPedalPosition, 0);
+ REGISTERPROPERTY(Chime, false);
+ REGISTERPROPERTY(WheelTick, 0);
+ REGISTERPROPERTY(IgnitionTimeOff, 0);
+ REGISTERPROPERTY(IgnitionTimeOn, 0);
+ REGISTERPROPERTY(YawRate, 0);
+ REGISTERPROPERTY(ButtonEventW3C, "");
}
void VehicleProperty::factory()
{
if(!thereCanOnlyBeOne)
- thereCanOnlyBeOne = new VehicleProperty();
-}
-
-void VehicleProperty::shutdown()
-{
- if(thereCanOnlyBeOne){
- delete thereCanOnlyBeOne;
- thereCanOnlyBeOne = nullptr;
- }
- registeredPropertyFactoryMap.clear();
- mCapabilities.clear();
- mCustomProperties.clear();
+ thereCanOnlyBeOne = amb::make_unique(new VehicleProperty());
}
PropertyList VehicleProperty::capabilities()
diff --git a/lib/vehicleproperty.h b/lib/vehicleproperty.h
index 3c5b97d5..a79e4ce1 100644
--- a/lib/vehicleproperty.h
+++ b/lib/vehicleproperty.h
@@ -48,6 +48,25 @@ enum ButtonEventType {
NavigateLeftButton = 1 << 11,
NavigateRightButton = 1 << 12
};
+
+namespace W3C
+{
+extern const char* Home;
+extern const char* Back;
+extern const char* Search;
+extern const char* Call;
+extern const char* EndCall;
+extern const char* MediaPlay;
+extern const char* MediaNext;
+extern const char* MediaPrevious;
+extern const char* MediaPause;
+extern const char* VoiceRecognize;
+extern const char* Enter;
+extern const char* Left;
+extern const char* Right;
+extern const char* Up;
+extern const char* Down;
+}
}
namespace TurnSignals {
@@ -334,12 +353,6 @@ public:
*/
static void factory();
- /*!
- *
- * \brief destroys static instance of VehicleProperty. This should be called at application shutdown
- */
- static void shutdown();
-
typedef std::string Property;
/*!
@@ -439,7 +452,7 @@ public:
/**< Engine coolant temperature in degrees celcius **/
static const Property EngineCoolantTemperature;
- PROPERTYTYPE(EngineCoolantTemperature, EngineCoolantTemperatureType, BasicPropertyType<int>, int)
+ PROPERTYTYPEBASIC(EngineCoolantTemperature, int16_t)
static const Property EngineCoolantLevel;
PROPERTYTYPE(EngineCoolantLevel, EngineCoolantLevelType, BasicPropertyType<uint>, uint)
@@ -448,17 +461,14 @@ public:
static const Property MachineGunTurretStatus;
PROPERTYTYPEBASIC(MachineGunTurretStatus, bool)
- /**< Acceleration on the 'x' axis in 1/1000 gravitational acceleration "g-force" */
static const Property AccelerationX;
- PROPERTYTYPE(AccelerationX, AccelerationXType, BasicPropertyType<uint16_t>, uint16_t)
+ PROPERTYTYPEBASIC(AccelerationX, int16_t)
- /**< Acceleration on the 'y' axis in 1/1000 gravitational acceleration "g-force" */
static const Property AccelerationY;
- PROPERTYTYPE(AccelerationY, AccelerationYType, BasicPropertyType<uint16_t>, uint16_t)
+ PROPERTYTYPEBASIC(AccelerationY, int16_t)
- /**< Acceleration on the 'z' axis in 1/1000 gravitational acceleration "g-force" */
static const Property AccelerationZ;
- PROPERTYTYPE(AccelerationZ, AccelerationZType, BasicPropertyType<uint16_t>, uint16_t)
+ PROPERTYTYPEBASIC(AccelerationZ, int16_t)
/**< Mass Air Flow. grams/sec */
static const Property MassAirFlow;
@@ -466,9 +476,12 @@ public:
//typedef BasicPropertyType<uint16_t> MassAirFlowType;
/**< Button Event @see ButtonEvents::ButtonEventType */
+ ///TODO: deprecated. Use ButtonEventW3C. Remove in 0.14
static const Property ButtonEvent;
PROPERTYTYPE(ButtonEvent, ButtonEventType, BasicPropertyType<ButtonEvents::ButtonEventType>, ButtonEvents::ButtonEventType)
- //typedef BasicPropertyType<ButtonEvents::ButtonEventType> ButtonEventType;
+
+ static const Property ButtonEventW3C;
+ PROPERTYTYPE(ButtonEventW3C, ButtonEventW3CType, StringPropertyType, std::string)
/**< Air intake temperature in degrees celcius */
static const Property AirIntakeTemperature;
@@ -496,14 +509,17 @@ public:
PROPERTYTYPE(ExteriorTemperature, ExteriorTemperatureType, BasicPropertyType<int>, int)
//typedef BasicPropertyType<int> ExteriorTemperatureType;
- /**< Engine Oil Temperature in degrees celcius */
static const Property EngineOilTemperature;
- PROPERTYTYPE(EngineOilTemperature, EngineOilTemperatureType, BasicPropertyType<int>, int)
- //typedef BasicPropertyType<int> EngineOilTemperatureType;
+ PROPERTYTYPEBASIC(EngineOilTemperature, int)
static const Property EngineOilRemaining;
- PROPERTYTYPE(EngineOilRemaining, EngineOilRemainingType,BasicPropertyType<uint16_t>, uint16_t)
- //typedef BasicPropertyType<uint16_t> EngineOilRemainingType;
+ PROPERTYTYPEBASIC(EngineOilRemaining, uint16_t)
+
+ static const Property EngineOilLifeRemaining;
+ PROPERTYTYPEBASIC(EngineOilLifeRemaining, uint8_t)
+
+ static const Property EngineOilChangeIndicator;
+ PROPERTYTYPEBASIC(EngineOilChangeIndicator, bool)
/**< Vehicle Identification Number (ISO 3779) 17 chars**/
static const Property VIN;
@@ -567,14 +583,19 @@ public:
static const Property LightDynamicHighBeam;
PROPERTYTYPEBASIC(LightDynamicHighBeam, bool)
-
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
static const Property InteriorLightDriver;
PROPERTYTYPE(InteriorLightDriver, InteriorLightDriverType, BasicPropertyType<bool>, bool)
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
static const Property InteriorLightCenter;
PROPERTYTYPE(InteriorLightCenter, InteriorLightCenterType, BasicPropertyType<bool>, bool)
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
static const Property InteriorLightPassenger;
PROPERTYTYPE(InteriorLightPassenger, InteriorLightPassengerType, BasicPropertyType<bool>, bool)
+ static const Property InteriorLightStatus;
+ PROPERTYTYPEBASIC(InteriorLightStatus, bool)
+
static const Property EngineLoad;
PROPERTYTYPE(EngineLoad, EngineLoadType, BasicPropertyType<uint16_t>, uint16_t)
@@ -879,6 +900,26 @@ public:
static const Property DriverId;
PROPERTYTYPE(DriverId, DriverIdType, StringPropertyType, std::string)
+ static const Property PowertrainTorque;
+ PROPERTYTYPEBASIC(PowertrainTorque, uint16_t)
+
+ static const Property AcceleratorPedalPosition;
+ PROPERTYTYPEBASIC(AcceleratorPedalPosition, uint8_t)
+
+ static const Property Chime;
+ PROPERTYTYPEBASIC(Chime, bool)
+
+ static const Property WheelTick;
+ PROPERTYTYPEBASIC(WheelTick, uint)
+
+ static const Property IgnitionTimeOn;
+ PROPERTYTYPEBASIC(IgnitionTimeOn, uint64_t)
+
+ static const Property IgnitionTimeOff;
+ PROPERTYTYPEBASIC(IgnitionTimeOff, uint64_t)
+
+ static const Property YawRate;
+ PROPERTYTYPEBASIC(YawRate, int16_t)
/** END PROPERTIES **/
@@ -928,7 +969,7 @@ private:
VehicleProperty();
- static VehicleProperty* thereCanOnlyBeOne;
+ static std::unique_ptr<VehicleProperty> thereCanOnlyBeOne;
static bool registerPropertyPriv(Property name, PropertyTypeFactoryCallback factory);
diff --git a/plugins/bluemonkey/bluemonkey.cpp b/plugins/bluemonkey/bluemonkey.cpp
index a7f0785c..f2fb0489 100644
--- a/plugins/bluemonkey/bluemonkey.cpp
+++ b/plugins/bluemonkey/bluemonkey.cpp
@@ -181,7 +181,7 @@ void BluemonkeySink::loadConfig(QString str)
QFile file(str);
if(!file.open(QIODevice::ReadOnly))
{
- DebugOut()<<"failed to open config file: "<<str.toStdString()<<endl;
+ DebugOut(DebugOut::Error)<<"failed to open config file: "<<str.toStdString()<<endl;
return;
}
@@ -322,7 +322,7 @@ void BluemonkeySink::getHistory(QStringList properties, QDateTime begin, QDateTi
routingEngine->getRangePropertyAsync(request);
}
-void BluemonkeySink::createCustomProperty(QString name, QJSValue defaultValue, Zone::Type zone = Zone::None)
+void BluemonkeySink::createCustomProperty(QString name, QJSValue defaultValue, int zone = Zone::None)
{
auto create = [defaultValue, name]() -> AbstractPropertyType*
diff --git a/plugins/bluemonkey/bluemonkey.h b/plugins/bluemonkey/bluemonkey.h
index 13ee9bae..2a08856e 100644
--- a/plugins/bluemonkey/bluemonkey.h
+++ b/plugins/bluemonkey/bluemonkey.h
@@ -88,7 +88,11 @@ private:
class BluemonkeySink : public QObject, public AmbPluginImpl
{
Q_OBJECT
+
public:
+ using AmbPluginImpl::setProperty;
+ using QObject::setProperty;
+
BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource& parent);
virtual PropertyList subscriptions();
virtual void supportedChanged(const PropertyList & supportedProperties);
@@ -137,7 +141,7 @@ public Q_SLOTS:
mSilentMode = m;
}
- void createCustomProperty(QString name, QJSValue defaultValue, Zone::Type zone);
+ void createCustomProperty(QString name, QJSValue defaultValue, int zone);
private:
QStringList configsToLoad;
diff --git a/plugins/cangenplugin/cangenplugin.cpp b/plugins/cangenplugin/cangenplugin.cpp
index 5ed91b97..c5ccdd6d 100644
--- a/plugins/cangenplugin/cangenplugin.cpp
+++ b/plugins/cangenplugin/cangenplugin.cpp
@@ -88,7 +88,7 @@ AsyncPropertyReply *CANGenPlugin::setProperty(const AsyncSetPropertyRequest &req
{
std::string v = request.value->toString();
- dataReceived(nullptr,v.c_str(),v.length());
+ dataReceived(nullptr, v.c_str(), v.length());
}
return AmbPluginImpl::setProperty(request);
@@ -408,13 +408,13 @@ void CANGenPlugin::dataReceived(libwebsocket* socket, const char* data, size_t l
}
else if (name == "set")
{
+ LOG_MESSAGE("set called");
if (!propertyNames.empty())
{
//Should not happen
}
else if (!propertyData.empty())
{
- auto prop = propertyData.begin();
for (auto prop = propertyData.begin(); prop != propertyData.end(); ++prop)
{
LOG_MESSAGE("websocketsinkmanager setting " << std::get<1>(*prop) << " to " << std::get<2>(*prop) << " in zone " << std::get<3>(*prop));
diff --git a/plugins/common/ambplugin.h b/plugins/common/ambplugin.h
index 47191280..47fc94e4 100644
--- a/plugins/common/ambplugin.h
+++ b/plugins/common/ambplugin.h
@@ -207,7 +207,9 @@ void AmbPlugin<T>::getRangePropertyAsync(AsyncRangePropertyReply *reply)
template<typename T>
AsyncPropertyReply* AmbPlugin<T>::setProperty(AsyncSetPropertyRequest request)
{
- return d ? d->AmbPluginImpl::setProperty(request) : nullptr;
+ if(d)
+ return d->setProperty(request);
+ return nullptr;
}
template<typename T>
diff --git a/plugins/database/databasesink.cpp b/plugins/database/databasesink.cpp
index dbc141e4..ae18d36a 100644
--- a/plugins/database/databasesink.cpp
+++ b/plugins/database/databasesink.cpp
@@ -122,7 +122,6 @@ int getNextEvent(gpointer data)
pbshared->playbackQueue.remove(obj);
DebugOut()<<"playback Queue size: "<<pbshared->playbackQueue.size()<<endl;
- //delete obj;
return 0;
}
@@ -329,16 +328,14 @@ void DatabaseSink::startPlayback()
obj.key = results[i][0];
obj.value = results[i][1];
obj.source = results[i][2];
- obj.time = boost::lexical_cast<double>(results[i][3]);
-
- /// TODO: figure out why sequence is broken:
-
-// obj->sequence = boost::lexical_cast<int>(results[i][4]);
+ obj.zone = boost::lexical_cast<double>(results[i][3]);
+ obj.time = boost::lexical_cast<double>(results[i][4]);
+ obj.sequence = boost::lexical_cast<double>(results[i][5]);
playbackShared->playbackQueue.push_back(obj);
}
- g_timeout_add(0,getNextEvent,playbackShared);
+ g_timeout_add(0, getNextEvent, playbackShared);
}
void DatabaseSink::initDb()
diff --git a/plugins/database/databasesink.h b/plugins/database/databasesink.h
index 2ec319f1..bb9697ae 100644
--- a/plugins/database/databasesink.h
+++ b/plugins/database/databasesink.h
@@ -172,7 +172,8 @@ public:
bool operator ==(const DBObject & other) const
{
- return (key == other.key && source == other.source && zone == other.zone);
+ return (key == other.key && source == other.source && zone == other.zone &&
+ value == other.value && sequence == other.sequence && time == other.time);
}
bool operator != (const DBObject & other)
diff --git a/plugins/dbus/automotivemanager.cpp b/plugins/dbus/automotivemanager.cpp
index 7955ac89..da49d9c2 100644
--- a/plugins/dbus/automotivemanager.cpp
+++ b/plugins/dbus/automotivemanager.cpp
@@ -124,7 +124,7 @@ static void handleMethodCall(GDBusConnection *connection,
if(propertyToFind == "")
{
- g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
return;
}
@@ -132,7 +132,7 @@ static void handleMethodCall(GDBusConnection *connection,
if(!interfaces.size())
{
- g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ g_dbus_method_invocation_return_dbus_error(invocation, "org.automotive.Manager.ObjectNotFound", "Property not found");
return;
}
@@ -160,7 +160,7 @@ static void handleMethodCall(GDBusConnection *connection,
}
}
- g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.InvalidZone", "zone not found");
}
else if (method == "ZonesForObjectName")
@@ -198,7 +198,7 @@ static void handleMethodCall(GDBusConnection *connection,
g_dbus_method_invocation_return_value(invocation,g_variant_new("(ai)",&params));
}
-
+
else if(method == "List")
{
std::list<AbstractDBusInterface*> list = AbstractDBusInterface::interfaces();
diff --git a/plugins/dbus/dbusinterfacemanager.cpp b/plugins/dbus/dbusinterfacemanager.cpp
index 3ca7f279..4200784b 100644
--- a/plugins/dbus/dbusinterfacemanager.cpp
+++ b/plugins/dbus/dbusinterfacemanager.cpp
@@ -218,6 +218,12 @@ on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_d
exportProperty<EngineCoolant>(iface->re, connection);
exportProperty<NightMode>(iface->re, connection);
exportProperty<DrivingMode>(iface->re, connection);
+ exportProperty<PowertrainTorque>(iface->re, connection);
+ exportProperty<AcceleratorPedalPosition>(iface->re, connection);
+ exportProperty<Chime>(iface->re, connection);
+ exportProperty<WheelTick>(iface->re, connection);
+ exportProperty<IgnitionTime>(iface->re, connection);
+ exportProperty<YawRate>(iface->re, connection);
iface->registerCustomTypes();
}
diff --git a/plugins/dbus/environmentproperties.h b/plugins/dbus/environmentproperties.h
index 10db753c..3815152d 100644
--- a/plugins/dbus/environmentproperties.h
+++ b/plugins/dbus/environmentproperties.h
@@ -28,7 +28,7 @@ class Temperature: public DBusSink
{
public:
Temperature(AbstractRoutingEngine* re, GDBusConnection* connection)
- :DBusSink("InteriorTemperature", re, connection, map<string, string>())
+ :DBusSink("Temperature", re, connection, map<string, string>())
{
/**
* @attributeName Interior
diff --git a/plugins/dbus/runningstatus.h b/plugins/dbus/runningstatus.h
index 38f0b873..d66d4c64 100644
--- a/plugins/dbus/runningstatus.h
+++ b/plugins/dbus/runningstatus.h
@@ -116,26 +116,9 @@ public:
AccelerationProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("Acceleration", re, connection, map<string, string>())
{
- /** @attributeName X
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return acceleration on the "X" axis as 1/1000 G (gravitational force).
- **/
- wantPropertyVariant(VehicleProperty::AccelerationX, "X", "q", AbstractProperty::Read);
-
- /** @attributeName Y
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return acceleration on the "Y" axis as 1/1000 G (gravitational force).
- **/
- wantPropertyVariant(VehicleProperty::AccelerationY, "Y", "q", AbstractProperty::Read);
-
- /** @attributeName Z
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return acceleration on the "Z" axis as 1/1000 G (gravitational force).
- **/
- wantPropertyVariant(VehicleProperty::AccelerationZ, "Z", "q", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::AccelerationX, "X", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::AccelerationY, "Y", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::AccelerationZ, "Z", AbstractProperty::Read);
}
};
@@ -171,25 +154,15 @@ public:
CruiseControlProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("CruiseControlStatus", re, connection, map<string, string>())
{
- /** @attributeName Activated
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return whether or not the Cruise Control system is active (true) or inactive (false)
- **/
- wantPropertyVariant(VehicleProperty::CruiseControlActive, "Activated", "b", AbstractProperty::Read);
-
- /** @attributeName Speed
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return target Cruise Control speed in kilometers per hour (kph).
- **/
- wantPropertyVariant(VehicleProperty::CruiseControlSpeed, "Speed", "q", AbstractProperty::Read);
-
+ ///TODO: deprecate Activated. Remove in 0.14
+ wantPropertyVariant(VehicleProperty::CruiseControlActive, "Activated", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::CruiseControlSpeed, "Speed", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::CruiseControlActive, "Status", AbstractProperty::Read);
}
};
/** @interface WheelBrake : VehiclePropertyType **/
-/// TODO: deprecated remove in 0.13
+/// TODO: deprecated remove in 0.14
class WheelBrakeProperty: public DBusSink
{
public:
@@ -218,7 +191,7 @@ public:
* @access readonly
* @attributeComment \brief Must return Wheel Brake status: Engaged = true, disengaged = false
**/
- wantPropertyVariant(VehicleProperty::WheelBrake, "brakePedalDepressed", "b", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::WheelBrake, "BrakePedalDepressed", AbstractProperty::Read);
}
};
@@ -230,96 +203,34 @@ public:
LightStatusProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("LightStatus", re, connection, map<string, string>())
{
- /** @attributeName Head
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return headlight status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightHead, "Head", "b", AbstractProperty::Read);
-
- /** @attributeName RightTurn
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return right turn signal status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightRightTurn, "RightTurn", "b", AbstractProperty::Read);
-
- /** @attributeName LeftTurn
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return left turn signal status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightLeftTurn, "LeftTurn", "b", AbstractProperty::Read);
-
- /** @attributeName Brake
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return brake signal light status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightBrake, "Brake", "b", AbstractProperty::Read);
-
- /** @attributeName Fog
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return fog light status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightFog, "Fog", "b", AbstractProperty::Read);
-
- /** @attributeName Hazard
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return hazard light status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightHazard, "Hazard", "b", AbstractProperty::Read);
-
- /** @attributeName Parking
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return parking light status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightParking, "Parking", "b", AbstractProperty::Read);
-
- /** @attributeName HighBeam
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return high beam status: on = true, off = false.
- **/
- wantPropertyVariant(VehicleProperty::LightHighBeam, "HighBeam", "b", AbstractProperty::Read);
-
- wantPropertyVariant(VehicleProperty::LightAutomatic, "automaticHeadlights", AbstractProperty::Read);
- wantPropertyVariant(VehicleProperty::LightDynamicHighBeam, "dynamicHighBeam", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::LightHead, "Head", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightRightTurn, "RightTurn", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightLeftTurn, "LeftTurn", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightBrake, "Brake", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightFog, "Fog", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightHazard, "Hazard", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightParking, "Parking", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightHighBeam, "HighBeam", "b", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightAutomatic, "AutomaticHeadlights", AbstractProperty::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightDynamicHighBeam, "DynamicHighBeam", AbstractProperty::ReadWrite);
}
};
-/** @interface InteriorLightStatus : VehiclePropertyType **/
class InteriorLightStatusProperty: public DBusSink
{
public:
InteriorLightStatusProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("InteriorLightStatus", re, connection, map<string, string>())
{
- /** @attributeName Passenger
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return passenger interior light status: on = true, off = false
- **/
- wantPropertyVariant(VehicleProperty::InteriorLightPassenger, "Passenger", "b", AbstractProperty::Read);
-
- /** @attributeName Driver
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return driver interior light status: on = true, off = false
- **/
- wantPropertyVariant(VehicleProperty::InteriorLightPassenger, "Driver", "b", AbstractProperty::Read);
-
- /** @attributeName Center
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return center interior light status: on = true, off = false
- **/
- wantPropertyVariant(VehicleProperty::InteriorLightCenter, "Center", "b", AbstractProperty::Read);
-
+ /// TODO: deprecated remove in 0.14
+ wantPropertyVariant(VehicleProperty::InteriorLightPassenger, "Passenger", AbstractProperty::Read);
+ /// TODO: deprecated remove in 0.14
+ wantPropertyVariant(VehicleProperty::InteriorLightPassenger, "Driver", AbstractProperty::Read);
+ /// TODO: deprecated remove in 0.14
+ wantPropertyVariant(VehicleProperty::InteriorLightCenter, "Center", AbstractProperty::Read);
+
+ wantPropertyVariant(VehicleProperty::InteriorLightStatus, "Status", AbstractProperty::ReadWrite);
}
};
@@ -330,12 +241,9 @@ public:
HornProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("Horn", re, connection, map<string, string>())
{
- /** @attributeName On
- * @type boolean
- * @access readonly
- * @attributeComment \brief Must return horn status: on = true, off = false
- **/
- wantPropertyVariant(VehicleProperty::Horn,"On","b",AbstractProperty::Read);
+ /// TODO: deprecated remove in 0.14
+ wantPropertyVariant(VehicleProperty::Horn,"On",AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::Horn,"Status",AbstractProperty::Read);
}
};
@@ -373,26 +281,13 @@ public:
EngineOilProperty(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("EngineOil", re, connection, map<string, string>())
{
- /** @attributeName Remaining
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return remaining engine oil as percentage of fullness.
- **/
- wantPropertyVariant(VehicleProperty::EngineOilRemaining, "Remaining", "q", AbstractProperty::Read);
-
- /** @attributeName Temperature
- * @type long
- * @access readonly
- * @attributeComment \brief Must return Engine Oil Temperature in Celcius.
- **/
- wantPropertyVariant(VehicleProperty::EngineOilTemperature, "Temperature", "i", AbstractProperty::Read);
-
- /** @attributeName Pressure
- * @type unsigned short
- * @access readonly
- * @attributeComment \brief Must return Engine Oil Pressure in kPa.
- **/
- wantPropertyVariant(VehicleProperty::EngineOilPressure, "Pressure", "q", AbstractProperty::Read);
+ ///TODO depricated. Use Level. Remove in 0.14
+ wantPropertyVariant(VehicleProperty::EngineOilRemaining, "Remaining", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilRemaining, "Level", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilTemperature, "Temperature", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilPressure, "Pressure", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilChangeIndicator, "Change", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilLifeRemaining, "LifeRemaining", AbstractProperty::Read);
}
};
@@ -451,7 +346,7 @@ public:
ThrottlePosition(AbstractRoutingEngine *re, GDBusConnection *connection)
:DBusSink("ThrottlePosition", re, connection, map<string, string>())
{
- wantPropertyVariant(VehicleProperty::ThrottlePosition, "Value", "i", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::ThrottlePosition, "Value", AbstractProperty::Read);
}
};
@@ -477,4 +372,65 @@ public:
}
};
+class PowertrainTorque: public DBusSink
+{
+public:
+ PowertrainTorque(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("PowertrainTorque", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::PowertrainTorque, "Value", AbstractProperty::Read);
+ }
+};
+
+class AcceleratorPedalPosition: public DBusSink
+{
+public:
+ AcceleratorPedalPosition(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("AcceleratorPedalPosition", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AcceleratorPedalPosition, "Value", AbstractProperty::Read);
+ }
+};
+
+class Chime: public DBusSink
+{
+public:
+ Chime(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Chime", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::Chime, "Status", AbstractProperty::Read);
+ }
+};
+
+class WheelTick: public DBusSink
+{
+public:
+ WheelTick(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("WheelTick", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WheelTick, "Value", AbstractProperty::Read);
+ }
+};
+
+class IgnitionTime: public DBusSink
+{
+public:
+ IgnitionTime(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("IgnitionTime", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::IgnitionTimeOn, "IgnitionTimeOn", AbstractProperty::Read);
+ wantPropertyVariant(VehicleProperty::IgnitionTimeOff, "IgnitionTimeOff", AbstractProperty::Read);
+ }
+};
+
+class YawRate: public DBusSink
+{
+public:
+ YawRate(AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("YawRate", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::YawRate, "Value", AbstractProperty::Read);
+ }
+};
+
#endif
diff --git a/plugins/obd2plugin/obd2source.cpp b/plugins/obd2plugin/obd2source.cpp
index c95bda20..1be11126 100644
--- a/plugins/obd2plugin/obd2source.cpp
+++ b/plugins/obd2plugin/obd2source.cpp
@@ -277,7 +277,7 @@ void threadLoop(gpointer data)
connected = false;
StatusMessage *statusreq = new StatusMessage();
statusreq->statusStr = "disconnected";
- g_async_queue_push(privStatusQueue,statusreq);
+ g_async_queue_push(privStatusQueue, statusreq);
}
delete req;
}
@@ -468,7 +468,7 @@ static int updateProperties( gpointer data)
}
else if (reply->statusStr == "connected")
{
- src->obd2Connected.setValue(false);
+ src->obd2Connected.setValue(true);
src->updateProperty(&src->obd2Connected);
}
else if (reply->statusStr == "error:nodata" || reply->statusStr == "error:timeout")
@@ -519,11 +519,10 @@ static int updateProperties( gpointer data)
void OBD2Source::updateProperty(AbstractPropertyType* value)
{
VehicleProperty::Property property = value->name;
- if(property == Obd2Connected)
- obd2Connected.setValue(value->anyValue());
-
AsyncPropertyReply* reply = nullptr;
+ DebugOut() << "updateProperty for: " << property << "value: " << value->toString() << endl;
+
for(auto i : propertyReplyList)
{
if(i->property == property)
@@ -547,24 +546,28 @@ void OBD2Source::updateProperty(AbstractPropertyType* value)
removeOne(&propertyReplyList, reply);
}
- else
- {
- if(oldValueMap.find(property) != oldValueMap.end())
- {
- AbstractPropertyType* old = oldValueMap[property];
- if((*old) == (*value))
- {
- return;
- }
+ if(oldValueMap.find(property) != oldValueMap.end())
+ {
+ AbstractPropertyType* old = oldValueMap[property];
- delete old;
+ if((*old) == (*value))
+ {
+ DebugOut() << "old value is same as new for: " << value->name << endl;
+ return;
}
+ delete old;
+ oldValueMap.erase(property);
+ }
+ else
+ {
oldValueMap[property] = value->copy();
-
- m_re->updateProperty(value, uuid());
}
+
+ DebugOut() << "updateProperty for: " << property << "value: " << value->toString() << endl;
+ m_re->updateProperty(value, uuid());
+
}
void OBD2Source::setSupported(PropertyList list)
@@ -616,22 +619,6 @@ void OBD2Source::setConfiguration(map<string, string> config)
m_btDeviceAddress = port;
m_btAdapterAddress = btadapter;
m_isBluetooth = true;
- ///TODO: bluetooth!!
- /*DebugOut()<<"bluetooth device?"<<endl;
- BluetoothDevice bt;
-
- std::string tempPort = bt.getDeviceForAddress(port, btadapter);
- if(tempPort != "")
- {
- DebugOut(3)<<"Using bluetooth device \""<<port<<"\" bound to: "<<tempPort<<endl;
- port = tempPort;
- }
- else
- {
- DebugOut(0)<<"Device Error"<<endl;
- ///Don't throw here.
- //throw std::runtime_error("Device Error");
- }*/
}
//connect(obd, port, baud);
@@ -639,19 +626,18 @@ void OBD2Source::setConfiguration(map<string, string> config)
req->req = "setportandbaud";
req->arglist.push_back(port);
req->arglist.push_back(baud);
- g_async_queue_push(commandQueue,req);
+ g_async_queue_push(commandQueue, req);
m_port = port;
m_baud = baud;
- m_gThread = g_thread_new("mythread",(GThreadFunc)&threadLoop,this);
- //g_idle_add(updateProperties, this);
- g_timeout_add(5,updateProperties,this);
+ m_gThread = g_thread_new("mythread", (GThreadFunc)&threadLoop, this);
+ g_timeout_add(5, updateProperties, this);
}
OBD2Source::OBD2Source(AbstractRoutingEngine *re, map<string, string> config)
- : AbstractSource(re, config),obd2Connected(Obd2Connected,false)
+ : AbstractSource(re, config), obd2Connected(Obd2Connected,false)
{
- bool success = VehicleProperty::registerProperty(Obd2Connected,[](){ return new Obd2ConnectType(Obd2Connected,false); });
+ bool success = VehicleProperty::registerProperty(Obd2Connected, [](){ return new Obd2ConnectType(Obd2Connected, false); });
if(!success)
{
diff --git a/plugins/opencvlux/CMakeLists.txt b/plugins/opencvlux/CMakeLists.txt
index acb48ed7..f7ef01c7 100644
--- a/plugins/opencvlux/CMakeLists.txt
+++ b/plugins/opencvlux/CMakeLists.txt
@@ -1,15 +1,19 @@
if(opencvlux_plugin)
+set(qtmainloop "ON")
+
find_package(OpenCV REQUIRED)
if(OpenCV_LIBS)
- message(STATUS "opencv found")
+ message(STATUS "opencv found: ${OpenCV_INCLUDE_DIRS}")
else(OpenCV_LIBS)
message(FATAL_ERROR "opencv missing. please install opencv")
endif(OpenCV_LIBS)
option(ocl "enable opencl" OFF)
+add_definitions(-DCV_DATA="${OpenCV_CONFIG_PATH}")
+
if(ocl)
message(STATUS "found opencv ocl headers. enabling opencl support. ${ocl}")
add_definitions(-DOPENCL)
@@ -37,6 +41,7 @@ if(Qt5Core_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
message(STATUS "size of void_p: ${CMAKE_SIZEOF_VOID_P}")
add_definitions(${Qt5Core_DEFINITIONS})
+ add_definitions(-DQT_NO_KEYWORDS)
endif(Qt5Core_FOUND)
set(CMAKE_AUTOMOC ON)
diff --git a/plugins/opencvlux/README b/plugins/opencvlux/README
index 014dd8dd..9d88b6f4 100644
--- a/plugins/opencvlux/README
+++ b/plugins/opencvlux/README
@@ -69,11 +69,7 @@ Default: "255"
"opencl" (experimental)
Use a specialized CPU/GPU device to calculate the mean pixel intensity. This will only work if OpenCV
-was compiled with OpenCL support. This plugin looks for the OpenCV ocl headers and adds support at
-compile time.
-
-NOTE: This option has not been tested because at implementation, OpenCL 1.2 was not available from devices
-on-hand.
+was compiled with OpenCL support. To enable openCL, pass -Docl=ON to cmake.
Default: "false"
@@ -85,3 +81,39 @@ NOTE: this does not appear to have a noticable impact on processing given the wa
this does however make memory usage explode.
Default: "false"
+
+"logging"
+Turn on video logging.
+
+Default: "false"
+
+"logfile"
+File to encode video to.
+
+Default: "/tmp/video.avi"
+
+"codec"
+Fourcc name of codec. See http://www.fourcc.org/codecs.php
+
+Default: "mjpg"
+
+"ddd" (experimental)
+Driver Drowsiness Detection. For a driver facing camera, detect whether or not eyes are
+open or closed. If closed for a period of time, DriverDrowsiness will change to "true".
+
+Default: "false"
+
+
+AMB Properties:
+
+VideoLogging
+Turn on and off video logging
+
+Type: bool
+Access: readwrite
+
+DriverDrowsiness
+True if the driver has been detected drowsy.
+
+Type: bool
+Access: readonly
diff --git a/plugins/opencvlux/opencvluxplugin.cpp b/plugins/opencvlux/opencvluxplugin.cpp
index d3874014..46fa62e6 100644
--- a/plugins/opencvlux/opencvluxplugin.cpp
+++ b/plugins/opencvlux/opencvluxplugin.cpp
@@ -19,9 +19,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "opencvluxplugin.h"
#include "timestamp.h"
#include <listplusplus.h>
+#include <superptr.hpp>
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/objdetect/objdetect.hpp>
#include <QFuture>
#include <QFutureWatcher>
@@ -39,13 +41,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
using namespace std;
const std::string VideoLogging = "VideoLogging";
+const std::string DriverDrowsiness = "DriverDrowsiness";
#include "debugout.h"
extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
{
VehicleProperty::registerProperty(VideoLogging, [](){
- return new BasicPropertyType<bool>(VideoLogging,false);
+ return new BasicPropertyType<bool>(VideoLogging, false);
+ });
+
+ VehicleProperty::registerProperty(DriverDrowsiness, [](){
+ return new OpenCvLuxPlugin::DriverDrowsinessType(DriverDrowsiness, false);
});
return new OpenCvLuxPlugin(routingengine, config);
@@ -54,7 +61,9 @@ extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<str
OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config)
:AbstractSource(re, config), lastLux(0), speed(0), latitude(0), longitude(0), extBrightness(new VehicleProperty::ExteriorBrightnessType(0))
{
- shared = new Shared;
+ driverDrowsiness = amb::make_unique(new DriverDrowsinessType(DriverDrowsiness, false));
+
+ shared = amb::make_unique(new Shared);
shared->parent = this;
shared->m_capture = NULL;
@@ -65,6 +74,7 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string>
shared->useOpenCl = false;
shared->useCuda = false;
shared->loggingOn = false;
+ shared->ddd = false;
shared->fps=30;
device="0";
@@ -115,6 +125,9 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string>
{
#ifdef OPENCL
shared->useOpenCl = config["opencl"] == "true";
+#else
+ DebugOut(DebugOut::Warning) << "You really don't have openCL support. Disabling." << endl;
+ shared->useOpenCl = false;
#endif
}
@@ -126,6 +139,16 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string>
#endif
}
+ if(config.find("ddd") != config.end())
+ {
+ shared->ddd = config["ddd"] == "true";
+ }
+
+ if(config.find("logging") != config.end())
+ {
+ shared->loggingOn = config["logging"] == "true";
+ }
+
#ifdef OPENCL
if(shared->useOpenCl)
@@ -185,14 +208,46 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string>
}
#endif
+ if(shared->ddd)
+ {
+#ifdef OPENCL
+ if(shared->useOpenCl)
+ {
+ faceCascade = amb::make_unique(new cv::ocl::OclCascadeClassifier());
+ eyeCascade = amb::make_unique(new cv::ocl::OclCascadeClassifier());
+ }
+ else
+#endif
+ {
+ faceCascade = amb::make_unique(new cv::CascadeClassifier());
+ eyeCascade = amb::make_unique(new cv::CascadeClassifier());
+ }
+
+ std::string faceFile = CV_DATA "/haarcascades/haarcascade_frontalface_alt.xml";
+ if(!faceCascade->load(faceFile))
+ {
+ DebugOut(DebugOut::Warning) << "Could not load face cascade: " << faceFile <<". Disabling ddd" << endl;
+ shared->ddd = false;
+ }
+
+ std::string eyeFile = CV_DATA "/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
+
+ if(!eyeCascade->load(eyeFile))
+ {
+ DebugOut(DebugOut::Warning) << "Could not load eye cascade: " << eyeFile <<". Disabling ddd" << endl;
+ shared->ddd = false;
+ }
+
+ }
+
routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed, this);
- routingEngine->subscribeToProperty(VehicleProperty::Latitude,this);
+ routingEngine->subscribeToProperty(VehicleProperty::Latitude, this);
routingEngine->subscribeToProperty(VehicleProperty::Longitude, this);
}
OpenCvLuxPlugin::~OpenCvLuxPlugin()
{
- delete shared->mWriter;
+
}
const string OpenCvLuxPlugin::uuid()
@@ -211,7 +266,7 @@ void OpenCvLuxPlugin::getPropertyAsync(AsyncPropertyReply *reply)
/// we want to turn on the camera for one shot to get an image and determine the intensity
if(init())
- grabImage(shared);
+ grabImage(shared.get());
}
if(reply->property == VehicleProperty::ExteriorBrightness)
@@ -263,7 +318,7 @@ void OpenCvLuxPlugin::subscribeToPropertyChanges(VehicleProperty::Property prope
if(!shared->mRequests.size())
{
if(init())
- g_timeout_add(1000 / shared->fps, grabImage, shared);
+ g_timeout_add(1000 / shared->fps, grabImage, shared.get());
}
shared->mRequests.push_back(property);
@@ -278,6 +333,7 @@ PropertyList OpenCvLuxPlugin::supported()
{
PropertyList props;
props.push_back(VehicleProperty::ExteriorBrightness);
+ props.push_back(DriverDrowsiness);
props.push_back(VideoLogging);
return props;
@@ -323,9 +379,12 @@ static int grabImage(void *data)
}
else
{
- *(shared->m_capture) >> m_image;
+ *(shared->m_capture.get()) >> m_image;
}
+ if(shared->ddd)
+ shared->parent->detectEyes(m_image);
+
if(shared->threaded)
{
QFutureWatcher<uint> *watcher = new QFutureWatcher<uint>();
@@ -413,14 +472,14 @@ bool OpenCvLuxPlugin::init()
{
if(!shared->m_capture && shared->kinect)
{
- shared->m_capture = new cv::VideoCapture(CV_CAP_OPENNI);
+ shared->m_capture = amb::make_unique(new cv::VideoCapture(CV_CAP_OPENNI));
}
else if(!shared->m_capture)
{
if(device == "")
- shared->m_capture = new cv::VideoCapture(0);
+ shared->m_capture = amb::make_unique(new cv::VideoCapture(0));
else
- shared->m_capture = new cv::VideoCapture(atoi(device.c_str()));
+ shared->m_capture = amb::make_unique(new cv::VideoCapture(atoi(device.c_str())));
}
if(!shared->m_capture->isOpened())
@@ -450,9 +509,7 @@ bool OpenCvLuxPlugin::init()
boost::algorithm::to_upper(codec);
- if(shared->mWriter) delete shared->mWriter;
-
- shared->mWriter = new cv::VideoWriter(filename, CV_FOURCC(codec.at(0), codec.at(1), codec.at(2), codec.at(3)),30,s);
+ shared->mWriter = amb::make_unique(new cv::VideoWriter(filename, CV_FOURCC(codec.at(0), codec.at(1), codec.at(2), codec.at(3)),30,s));
}
DebugOut()<<"camera frame width: "<<shared->m_capture->get(CV_CAP_PROP_FRAME_WIDTH)<<endl;
@@ -470,8 +527,6 @@ void OpenCvLuxPlugin::writeVideoFrame(cv::Mat f)
if(shared->loggingOn && speed > 0)
{
-
-
cv::Mat frame;
f.copyTo(frame);
@@ -511,8 +566,8 @@ void OpenCvLuxPlugin::writeVideoFrame(cv::Mat f)
cv::putText(frame, datestr.str(), dateOrg, fontFace, fontScale,
cv::Scalar::all(255), thickness, 8);
- (*shared->mWriter)<<frame;
- (*shared->mWriter)<<frame;
+ (*shared->mWriter) << frame;
+ (*shared->mWriter) << frame;
}
}
@@ -611,7 +666,8 @@ TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared *shared)
}
else if(avgPixel[0] > 128 && avgPixel[1] < 128 && avgPixel[2] < 128)
{
- DebugOut(1)<<"Bluel Light!!!"<<endl;
+ DebugOut(1)<<"Yellow Light!!!"<<endl;
+ return TrafficLight::Yellow;
}
}
catch(...)
@@ -623,6 +679,72 @@ TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared *shared)
cv::namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
cv::imshow( "Hough Circle Transform Demo", img );
+}
+void OpenCvLuxPlugin::detectEyes(cv::Mat frame)
+{
+ if(frame.empty())
+ return;
+
+ bool hasEyes = false;
+ std::vector<cv::Rect> faces;
+ cv::Mat frameGray;
+#ifdef OPENCL
+ cv::ocl::oclMat gray2;
+#endif
+
+ if(shared->useOpenCl)
+ {
+#ifdef OPENCL
+ cv::ocl::oclMat src(frame);
+ cv::ocl::cvtColor(src, gray2, CV_BGR2GRAY);
+ cv::ocl::equalizeHist(gray2, gray2);
+ cv::ocl::OclCascadeClassifier* fc = static_cast<cv::ocl::OclCascadeClassifier*>(faceCascade.get());
+ fc->detectMultiScale(gray2, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30));
+#endif
+ }
+ else
+ {
+ cv::cvtColor(frame, frameGray, CV_BGR2GRAY);
+ cv::equalizeHist(frameGray, frameGray);
+ faceCascade->detectMultiScale(frameGray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30));
+ }
+
+ for( size_t i = 0; i < faces.size(); i++ )
+ {
+ cv::Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
+ cv::ellipse( frame, center, cv::Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, cv::Scalar( 255, 0, 255 ), 4, 8, 0 );
+
+ std::vector<cv::Rect> eyes;
+
+ if(shared->useOpenCl)
+ {
+#ifdef OPENCL
+ cv::ocl::oclMat faceROI = gray2(faces[i]);
+ cv::ocl::OclCascadeClassifier* ec = static_cast<cv::ocl::OclCascadeClassifier*>(eyeCascade.get());
+ ec->detectMultiScale( faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30) );
+#endif
+ }
+ else
+ {
+ cv::Mat faceROI = frameGray(faces[i]);
+ eyeCascade->detectMultiScale( faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30) );
+ }
+
+ if(eyes.size())
+ {
+ hasEyes = true;
+ DebugOut() << "Number of eyes: " << eyes.size() << endl;
+ }
+
+ for( size_t j = 0; j < eyes.size(); j++ )
+ {
+ cv::Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
+ int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
+ cv::circle( frame, center, radius, cv::Scalar( 255, 0, 0 ), 4, 8, 0 );
+ }
+ }
+
+ routingEngine->updateProperty(driverDrowsiness.get(),this->uuid());
}
diff --git a/plugins/opencvlux/opencvluxplugin.h b/plugins/opencvlux/opencvluxplugin.h
index 5f197711..9bb79302 100644
--- a/plugins/opencvlux/opencvluxplugin.h
+++ b/plugins/opencvlux/opencvluxplugin.h
@@ -36,10 +36,12 @@ class OpenCvLuxPlugin: public QObject, public AbstractSource
Q_OBJECT
public:
+ typedef BasicPropertyType<bool> DriverDrowsinessType;
+
struct Shared
{
- cv::VideoCapture *m_capture;
- cv::VideoWriter *mWriter;
+ std::unique_ptr<cv::VideoCapture> m_capture;
+ std::unique_ptr<cv::VideoWriter> mWriter;
PropertyList mRequests;
OpenCvLuxPlugin* parent;
@@ -51,6 +53,7 @@ public:
int pixelLowerBound;
int pixelUpperBound;
bool loggingOn;
+ bool ddd;
};
OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config);
@@ -75,6 +78,8 @@ public:
void writeVideoFrame(cv::Mat frame);
+ void detectEyes(cv::Mat frame);
+
public Q_SLOTS:
void imgProcResult();
@@ -83,6 +88,8 @@ private: /// methods:
bool init();
private:
+
+
uint speed;
uint latitude;
uint longitude;
@@ -93,8 +100,13 @@ private:
std::unique_ptr<VehicleProperty::ExteriorBrightnessType> extBrightness;
- Shared* shared;
+ std::unique_ptr<Shared> shared;
QMutex mutex;
+
+ std::unique_ptr<cv::CascadeClassifier> faceCascade;
+ std::unique_ptr<cv::CascadeClassifier> eyeCascade;
+
+ std::unique_ptr<DriverDrowsinessType> driverDrowsiness;
};
static int grabImage(void *data);
@@ -113,4 +125,5 @@ enum Color
TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared* shared);
+
#endif // EXAMPLEPLUGIN_H
diff --git a/xwalk/CMakeLists.txt b/xwalk/CMakeLists.txt
new file mode 100644
index 00000000..4cfd571b
--- /dev/null
+++ b/xwalk/CMakeLists.txt
@@ -0,0 +1,23 @@
+if(xwalk_vehicle_extension)
+
+pkg_check_modules(gio REQUIRED gio-2.0)
+
+set(vehicle_api_headers vehicle.h vehicle_instance.h vehicle_extension.h common/extension.h picojson.h common/utils.h common/virtual_fs.h
+ common/XW_Extension_EntryPoints.h common/XW_Extension.h common/XW_Permissions.h common/XW_Extension_Runtime.h common/XW_Extension_SyncMessage.h)
+set(vehicle_api_sources vehicle.cc vehicle_extension.cc vehicle_instance.cc common/extension.cc vehicle_api.cc)
+
+add_library(vehicle_extension MODULE ${vehicle_api_sources})
+
+include_directories(${include_dirs} ${CMAKE_CURRENT_SOURCE_DIR}/)
+target_link_libraries(vehicle_extension ${link_libraries} amb ${gio_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+add_custom_command(OUTPUT genjs2cc COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/generate_api.py ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js kSource_vehicle_api ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.cc )
+add_custom_target(js3cc DEPENDS genjs2cc)
+add_dependencies(vehicle_extension js3cc)
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html ${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html @ONLY)
+
+install(TARGETS vehicle_extension LIBRARY DESTINATION "${LIB_INSTALL_DIR}/${XWALK_EXTENSION_PATH}")
+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html DESTINATION /usr/share/automotive-message-broker/xwalk/examples)
+endif(xwalk_vehicle_extension)
diff --git a/xwalk/LICENSE b/xwalk/LICENSE
new file mode 100644
index 00000000..ac380b1a
--- /dev/null
+++ b/xwalk/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 Intel Corporation. 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 Intel Corporation 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/xwalk/common/XW_Extension.h b/xwalk/common/XW_Extension.h
new file mode 100644
index 00000000..174915ad
--- /dev/null
+++ b/xwalk/common/XW_Extension.h
@@ -0,0 +1,185 @@
+// 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.
+
+#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/xwalk/common/XW_Extension_EntryPoints.h b/xwalk/common/XW_Extension_EntryPoints.h
new file mode 100644
index 00000000..54532a91
--- /dev/null
+++ b/xwalk/common/XW_Extension_EntryPoints.h
@@ -0,0 +1,49 @@
+// 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.
+
+#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/xwalk/common/XW_Extension_Permissions.h b/xwalk/common/XW_Extension_Permissions.h
new file mode 100644
index 00000000..d25484ea
--- /dev/null
+++ b/xwalk/common/XW_Extension_Permissions.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2014 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.
+
+#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/xwalk/common/XW_Extension_Runtime.h b/xwalk/common/XW_Extension_Runtime.h
new file mode 100644
index 00000000..f5858f3e
--- /dev/null
+++ b/xwalk/common/XW_Extension_Runtime.h
@@ -0,0 +1,44 @@
+// 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.
+
+#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/xwalk/common/XW_Extension_SyncMessage.h b/xwalk/common/XW_Extension_SyncMessage.h
new file mode 100644
index 00000000..4eddbf9b
--- /dev/null
+++ b/xwalk/common/XW_Extension_SyncMessage.h
@@ -0,0 +1,48 @@
+// 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.
+
+#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/xwalk/common/extension.cc b/xwalk/common/extension.cc
new file mode 100644
index 00000000..168483a3
--- /dev/null
+++ b/xwalk/common/extension.cc
@@ -0,0 +1,212 @@
+// 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.
+
+#include "common/extension.h"
+
+#include <assert.h>
+#include <iostream>
+#include <vector>
+
+namespace {
+
+common::Extension* g_extension = NULL;
+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;
+
+bool InitializeInterfaces(XW_GetInterface get_interface) {
+ g_core = reinterpret_cast<const XW_CoreInterface*>(
+ get_interface(XW_CORE_INTERFACE));
+ if (!g_core) {
+ std::cerr << "Can't initialize extension: error getting Core interface.\n";
+ return false;
+ }
+
+ g_messaging = reinterpret_cast<const XW_MessagingInterface*>(
+ get_interface(XW_MESSAGING_INTERFACE));
+ if (!g_messaging) {
+ std::cerr <<
+ "Can't initialize extension: error getting Messaging interface.\n";
+ return false;
+ }
+
+ g_sync_messaging =
+ reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
+ get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
+ if (!g_sync_messaging) {
+ std::cerr <<
+ "Can't initialize extension: error getting SyncMessaging interface.\n";
+ return false;
+ }
+
+ g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
+ get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
+ if (!g_entry_points) {
+ std::cerr << "NOTE: Entry points interface not available in this version "
+ << "of Crosswalk, ignoring entry point data for extensions.\n";
+ }
+
+ g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
+ get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
+ if (!g_runtime) {
+ std::cerr << "NOTE: runtime interface not available in this version "
+ << "of Crosswalk, ignoring runtime variables for extensions.\n";
+ }
+
+ g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
+ get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
+ if (!g_permission) {
+ std::cerr << "NOTE: permission interface not available in this version "
+ << "of Crosswalk, ignoring permission for extensions.\n";
+ }
+
+ return true;
+}
+
+} // namespace
+
+int32_t XW_Initialize(XW_Extension extension, XW_GetInterface get_interface) {
+ assert(extension);
+ g_xw_extension = extension;
+
+ if (!InitializeInterfaces(get_interface))
+ return XW_ERROR;
+
+ g_extension = CreateExtension();
+ if (!g_extension) {
+ std::cerr << "Can't initialize extension: "
+ << "create extension returned NULL.\n";
+ return XW_ERROR;
+ }
+
+ using common::Extension;
+ g_core->RegisterShutdownCallback(g_xw_extension, Extension::OnShutdown);
+ g_core->RegisterInstanceCallbacks(
+ g_xw_extension, Extension::OnInstanceCreated,
+ Extension::OnInstanceDestroyed);
+ g_messaging->Register(g_xw_extension, Extension::HandleMessage);
+ g_sync_messaging->Register(g_xw_extension, Extension::HandleSyncMessage);
+ return XW_OK;
+}
+
+namespace common {
+
+Extension::Extension() {}
+
+Extension::~Extension() {}
+
+void Extension::SetExtensionName(const char* name) {
+ g_core->SetExtensionName(g_xw_extension, name);
+}
+
+void Extension::SetJavaScriptAPI(const char* api) {
+ g_core->SetJavaScriptAPI(g_xw_extension, api);
+}
+
+void Extension::SetExtraJSEntryPoints(const char** entry_points) {
+ if (g_entry_points)
+ g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points);
+}
+
+bool Extension::RegisterPermissions(const char* perm_table) {
+ if (g_permission)
+ return g_permission->RegisterPermissions(g_xw_extension, perm_table);
+ return false;
+}
+
+bool Extension::CheckAPIAccessControl(const char* api_name) {
+ if (g_permission)
+ return g_permission->CheckAPIAccessControl(g_xw_extension, api_name);
+ return false;
+}
+
+Instance* Extension::CreateInstance() {
+ return NULL;
+}
+
+std::string Extension::GetRuntimeVariable(const char* var_name, unsigned len) {
+ if (!g_runtime)
+ return "";
+
+ std::vector<char> res(len + 1, 0);
+ g_runtime->GetRuntimeVariableString(g_xw_extension, var_name, &res[0], len);
+ return std::string(res.begin(), res.end());
+}
+
+// static
+void Extension::OnShutdown(XW_Extension) {
+ delete g_extension;
+ g_extension = NULL;
+}
+
+// static
+void Extension::OnInstanceCreated(XW_Instance xw_instance) {
+ assert(!g_core->GetInstanceData(xw_instance));
+ Instance* instance = g_extension->CreateInstance();
+ if (!instance)
+ return;
+ instance->xw_instance_ = xw_instance;
+ g_core->SetInstanceData(xw_instance, instance);
+ instance->Initialize();
+}
+
+// static
+void Extension::OnInstanceDestroyed(XW_Instance xw_instance) {
+ 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) {
+ 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) {
+ Instance* instance =
+ reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+ if (!instance)
+ return;
+ instance->HandleSyncMessage(msg);
+}
+
+Instance::Instance()
+ : xw_instance_(0) {}
+
+Instance::~Instance() {
+ assert(xw_instance_ == 0);
+}
+
+void Instance::PostMessage(const char* msg) {
+ if (!xw_instance_) {
+ std::cerr << "Ignoring PostMessage() in the constructor or after the "
+ << "instance was destroyed.";
+ return;
+ }
+ g_messaging->PostMessage(xw_instance_, msg);
+}
+
+void Instance::SendSyncReply(const char* reply) {
+ if (!xw_instance_) {
+ std::cerr << "Ignoring SendSyncReply() in the constructor or after the "
+ << "instance was destroyed.";
+ return;
+ }
+ g_sync_messaging->SetSyncReply(xw_instance_, reply);
+}
+
+} // namespace common
diff --git a/xwalk/common/extension.h b/xwalk/common/extension.h
new file mode 100644
index 00000000..66d8bef0
--- /dev/null
+++ b/xwalk/common/extension.h
@@ -0,0 +1,96 @@
+// 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.
+
+#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 "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"
+
+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 {
+
+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();
+
+ static std::string GetRuntimeVariable(const char* var_name, unsigned len);
+
+ private:
+ friend int32_t ::XW_Initialize(XW_Extension extension,
+ XW_GetInterface get_interface);
+
+ // XW_Extension callbacks.
+ static void OnShutdown(XW_Extension xw_extension);
+ static void OnInstanceCreated(XW_Instance xw_instance);
+ 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);
+};
+
+class Instance {
+ public:
+ Instance();
+ virtual ~Instance();
+
+ void PostMessage(const char* msg);
+ void SendSyncReply(const char* reply);
+
+ virtual void Initialize() {}
+ virtual void HandleMessage(const char* msg) = 0;
+ virtual void HandleSyncMessage(const char* msg) {}
+
+ XW_Instance xw_instance() const { return xw_instance_; }
+
+ private:
+ friend class Extension;
+
+ XW_Instance xw_instance_;
+};
+
+} // namespace common
+
+#endif // COMMON_EXTENSION_H_
diff --git a/xwalk/common/picojson.h b/xwalk/common/picojson.h
new file mode 100644
index 00000000..9f983197
--- /dev/null
+++ b/xwalk/common/picojson.h
@@ -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 <cassert>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <string>
+#include <vector>
+
+#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/xwalk/common/utils.h b/xwalk/common/utils.h
new file mode 100644
index 00000000..ea866c43
--- /dev/null
+++ b/xwalk/common/utils.h
@@ -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.
+
+#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/xwalk/common/virtual_fs.cc b/xwalk/common/virtual_fs.cc
new file mode 100644
index 00000000..93984a0b
--- /dev/null
+++ b/xwalk/common/virtual_fs.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2014 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.
+
+#include "common/virtual_fs.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <pkgmgr-info.h>
+#include <tzplatform_config.h>
+
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "common/extension.h"
+
+namespace {
+
+const char kInternalStorage[] = "internal";
+const char kRemovableStorage[] = "removable";
+
+const char kStorageTypeInternal[] = "INTERNAL";
+const char kStorageTypeExternal[] = "EXTERNAL";
+const char kStorageStateMounted[] = "MOUNTED";
+const char kStorageStateRemoved[] = "REMOVED";
+const char kStorageStateUnmountable[] = "UNMOUNTABLE";
+
+} // namespace
+
+namespace vfs_const {
+
+const unsigned kDefaultFileMode = 0755;
+const char kLocationCamera[] = "camera";
+const char kLocationMusic[] = "music";
+const char kLocationImages[] = "images";
+const char kLocationVideos[] = "videos";
+const char kLocationDownloads[] = "downloads";
+const char kLocationDocuments[] = "documents";
+const char kLocationRingtones[] = "ringtones";
+const char kLocationWgtPackage[] = "wgt-package";
+const char kLocationWgtPrivate[] = "wgt-private";
+const char kLocationWgtPrivateTmp[] = "wgt-private-tmp";
+
+} // namespace vfs_const
+
+VirtualFS::VirtualFS() {
+ std::string app_path = GetApplicationPath();
+ if (!app_path.empty()) {
+ AddInternalStorage(vfs_const::kLocationWgtPackage, app_path);
+ AddInternalStorage(vfs_const::kLocationWgtPrivate, JoinPath(app_path, "private"));
+ AddInternalStorage(vfs_const::kLocationWgtPrivateTmp, JoinPath(app_path, "tmp"));
+ }
+
+ AddInternalStorage(vfs_const::kLocationCamera, tzplatform_getenv(TZ_USER_CAMERA));
+ AddInternalStorage(vfs_const::kLocationMusic, tzplatform_getenv(TZ_USER_SOUNDS));
+ AddInternalStorage(vfs_const::kLocationImages, tzplatform_getenv(TZ_USER_IMAGES));
+ AddInternalStorage(vfs_const::kLocationVideos, tzplatform_getenv(TZ_USER_VIDEOS));
+ AddInternalStorage(vfs_const::kLocationDownloads, tzplatform_getenv(TZ_USER_DOWNLOADS));
+ AddInternalStorage(vfs_const::kLocationDocuments, tzplatform_getenv(TZ_USER_DOCUMENTS));
+ AddInternalStorage(vfs_const::kLocationRingtones,
+ tzplatform_mkpath(TZ_USER_SHARE, "settings/Ringtones"));
+ storage_changed_cb_ = NULL;
+ cb_user_data_ = NULL;
+}
+
+VirtualFS::~VirtualFS() {
+}
+
+std::string VirtualFS::JoinPath(const std::string& one,
+ const std::string& another) {
+ return one + '/' + another;
+}
+
+bool VirtualFS::MakePath(const std::string& path, int mode) {
+ // Path should start with '/' and contain at least 1 character after '/'.
+ if (path.empty() || path[0] != '/' || path.length() < 2)
+ return false;
+
+ struct stat st;
+ std::string dir = path;
+ if (stat(dir.c_str(), &st) == 0)
+ return true;
+
+ // Add trailing '/' if missing, so we can iterate till the end of the path.
+ if (dir[dir.size() - 1] != '/')
+ dir += '/';
+
+ for (std::string::iterator iter = dir.begin(); iter != dir.end();) {
+ std::string::iterator cur_iter = std::find(iter, dir.end(), '/');
+
+ // If '/' is found at the beginning of the string, iterate to the next '/'.
+ if (cur_iter == iter) {
+ ++iter;
+ cur_iter = std::find(iter, dir.end(), '/');
+ }
+
+ std::string new_path = std::string(dir.begin(), cur_iter);
+
+ // If path doesn't exist, try to create one and continue iteration.
+ // In case of error, stop iteration and return.
+ if (stat(new_path.c_str(), &st) != 0) {
+ if (mkdir(new_path.c_str(), mode) != 0 && errno != EEXIST )
+ return false;
+ // If path exists and it is not a directory, stop iteration and return.
+ } else if (!S_ISDIR(st.st_mode)) {
+ return false;
+ }
+
+ // Advance iterator and create next parent folder.
+ iter = cur_iter;
+ if (cur_iter != dir.end())
+ ++iter;
+ }
+ return true;
+}
+
+int VirtualFS::GetDirEntryCount(const char* path) {
+ int count = 0;
+ DIR* dir = opendir(path);
+ if (!dir)
+ return count;
+
+ struct dirent entry;
+ struct dirent *result;
+ int ret = readdir_r(dir, &entry, &result);
+
+ for (; ret == 0 && result != NULL; ret = readdir_r(dir, &entry, &result)) {
+ if (entry.d_type == DT_REG || entry.d_type == DT_DIR)
+ count++;
+ }
+
+ closedir(dir);
+ return count;
+}
+
+std::string VirtualFS::GetAppId(const std::string& package_id) {
+ char* appid = NULL;
+ pkgmgrinfo_pkginfo_h pkginfo_handle;
+ int ret = pkgmgrinfo_pkginfo_get_pkginfo(package_id.c_str(), &pkginfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_pkginfo_get_mainappid(pkginfo_handle, &appid);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return std::string();
+ }
+
+ std::string retval(appid);
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return retval;
+}
+
+std::string VirtualFS::GetExecPath(const std::string& app_id) {
+ char* exec_path = NULL;
+ pkgmgrinfo_appinfo_h appinfo_handle;
+ int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &appinfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_appinfo_get_exec(appinfo_handle, &exec_path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return std::string();
+ }
+
+ std::string retval(exec_path);
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return retval;
+}
+
+bool VirtualFS::GetStorageByLabel(const std::string& label, Storage& storage) {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ Storages::const_iterator it = storages_.find(label);
+
+ if (it == storages_.end()) {
+ return false;
+ }
+ storage = it->second;
+ return true;
+}
+
+Storages::iterator VirtualFS::begin() {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ return storages_.begin();
+}
+
+Storages::const_iterator VirtualFS::end() const {
+ return storages_.end();
+}
+
+std::string VirtualFS::GetApplicationPath() {
+ std::string id_str = common::Extension::GetRuntimeVariable("app_id", 64);
+ std::string pkg_id = id_str.substr(1, id_str.rfind('"') - 1);
+ if (pkg_id.empty())
+ return std::string();
+ std::string app_id = GetAppId(pkg_id);
+ if (app_id.empty())
+ return std::string();
+ std::string exec_path = GetExecPath(app_id);
+ if (exec_path.empty())
+ return std::string();
+
+ size_t index = exec_path.find(pkg_id);
+ if (index != std::string::npos)
+ return exec_path.substr(0, index + pkg_id.length());
+ return std::string();
+}
+
+std::string VirtualFS::GetRealPath(const std::string& fullPath) const {
+ std::size_t pos = fullPath.find_first_of('/');
+ Storages::const_iterator it = storages_.find(fullPath.substr(0, pos));
+
+ if (it == storages_.end())
+ return std::string();
+
+ if (pos != std::string::npos)
+ return it->second.GetFullPath() + fullPath.substr(pos);
+
+ return it->second.GetFullPath();
+}
+
+void VirtualFS::AddInternalStorage(
+ const std::string& label, const std::string& path) {
+ if (MakePath(path, vfs_const::kDefaultFileMode))
+ storages_.insert(StorageLabelPair(label,
+ Storage(-1,
+ Storage::STORAGE_TYPE_INTERNAL,
+ Storage::STORAGE_STATE_MOUNTED,
+ path)));
+}
+
+void VirtualFS::AddStorage(int id,
+ storage_type_e type,
+ storage_state_e state,
+ const std::string& path) {
+ std::string label;
+ if (type == STORAGE_TYPE_INTERNAL)
+ label = kInternalStorage + std::to_string(id);
+ else if (type == STORAGE_TYPE_EXTERNAL)
+ label = kRemovableStorage + std::to_string(id);
+
+ storages_.insert(StorageLabelPair(label,
+ Storage(id,
+ type,
+ state,
+ path)));
+ if (std::find(watched_storages_.begin(),
+ watched_storages_.end(), id) != watched_storages_.end()) {
+ watched_storages_.push_back(id);
+ storage_set_state_changed_cb(id, OnStorageStateChanged, this);
+ }
+}
+
+void VirtualFS::SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data) {
+ storage_changed_cb_ = cb;
+ cb_user_data_ = user_data;
+}
+
+void VirtualFS::NotifyStorageStateChanged(int id, storage_state_e state) {
+ for (Storages::iterator it = storages_.begin(); it != storages_.end(); ++it) {
+ if (it->second.GetId() == id) {
+ it->second.SetState(state);
+ if (storage_changed_cb_) {
+ storage_changed_cb_(it->first, it->second, cb_user_data_);
+ }
+ break;
+ }
+ }
+}
+
+bool VirtualFS::OnStorageDeviceSupported(
+ int id, storage_type_e type, storage_state_e state,
+ const char* path, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->AddStorage(
+ id, type, state, path);
+ return true;
+}
+
+void VirtualFS::OnStorageStateChanged(
+ int id, storage_state_e state, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->NotifyStorageStateChanged(
+ id, state);
+}
+
+/*
+ * Storage Class
+ */
+
+Storage::Storage(
+ int id, int type, int state, const std::string& fullpath)
+ : id_(id),
+ type_(type),
+ state_(state),
+ full_path_(fullpath) { }
+
+std::string Storage::GetType() const {
+ return (type_ == Storage::STORAGE_TYPE_INTERNAL) ? kStorageTypeInternal :
+ kStorageTypeExternal;
+}
+
+std::string Storage::GetState() const {
+ switch (state_) {
+ case Storage::STORAGE_STATE_MOUNTED:
+ case Storage::STORAGE_STATE_MOUNTED_READONLY:
+ return kStorageStateMounted;
+ case Storage::STORAGE_STATE_REMOVED:
+ return kStorageStateRemoved;
+ case Storage::STORAGE_STATE_UNMOUNTABLE:
+ return kStorageStateUnmountable;
+ default:
+ assert(!"Not reached");
+ }
+ return std::string();
+}
diff --git a/xwalk/common/virtual_fs.h b/xwalk/common/virtual_fs.h
new file mode 100644
index 00000000..94a988f1
--- /dev/null
+++ b/xwalk/common/virtual_fs.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2014 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.
+
+#ifndef COMMON_VIRTUAL_FS_H_
+#define COMMON_VIRTUAL_FS_H_
+
+#include <appfw/app_storage.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace vfs_const {
+
+extern const unsigned kDefaultFileMode;
+extern const char kLocationCamera[];
+extern const char kLocationMusic[];
+extern const char kLocationImages[];
+extern const char kLocationVideos[];
+extern const char kLocationDownloads[];
+extern const char kLocationDocuments[];
+extern const char kLocationRingtones[];
+extern const char kLocationWgtPackage[];
+extern const char kLocationWgtPrivate[];
+extern const char kLocationWgtPrivateTmp[];
+
+} // namespace vfs_const
+
+class Storage {
+ public:
+ /* Mapped to storage_type_e */
+ enum StorageType {
+ STORAGE_TYPE_INTERNAL, STORAGE_TYPE_EXTERNAL,
+ };
+
+ /* Mapped to storage_state_e */
+ enum StorageState {
+ STORAGE_STATE_UNMOUNTABLE = -2,
+ STORAGE_STATE_REMOVED = -1,
+ STORAGE_STATE_MOUNTED = 0,
+ STORAGE_STATE_MOUNTED_READONLY = 1,
+ };
+
+ Storage(int id = 0, int type = 0, int state = 0,
+ const std::string& fullpath = "");
+
+ std::string GetType() const;
+ std::string GetState() const;
+ int GetId() const { return id_; }
+ const std::string& GetFullPath() const { return full_path_; }
+ void SetState(int state) { state_ = state; }
+
+ private:
+ int id_;
+ int type_;
+ int state_;
+ std::string full_path_;
+};
+
+typedef std::map<std::string, Storage> Storages;
+typedef void(*CallBackFunctionPtr)(const std::string&, Storage, void*);
+
+/**
+ * The VirtualFS class provide an abstraction of the TIZEN virtual filesystem.
+ * It manages mounted storages and virtual roots, creating missing directories
+ * if needed.
+ * Convenient functions are also provided for working with paths (real or
+ * virtual).
+ */
+class VirtualFS {
+ public:
+ VirtualFS();
+ ~VirtualFS();
+ /**
+ * Resolve the given fullpath within the virtual filesystem to an absolute
+ * path within the real filesystem.
+ * @param fullPath: fully-qualified path of the form: <root name>/<path>
+ * where <rootname> is the name of the virtual root and <path> is the path
+ * to the file or directory relative to that root.
+ * @return full Linux path.
+ */
+ std::string GetRealPath(const std::string& fullPath) const;
+ bool GetStorageByLabel(const std::string& label, Storage& storage);
+ Storages::iterator begin();
+ Storages::const_iterator end() const;
+ void SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data);
+
+ /**
+ * Concatenate two paths.
+ * @param one: base path.
+ * @param another: path within 'one'.
+ * @return new path.
+ */
+ static std::string JoinPath(const std::string& one,
+ const std::string& another);
+ /**
+ * Create full path and parent directories when needed.
+ * Similar to "mkdir -p".
+ * @param path: the path to be created.
+ * @param mode: the unix access mode applied to the new directories.
+ * @return true if success.
+ */
+ static bool MakePath(const std::string& path, int mode);
+ static int GetDirEntryCount(const char* path);
+ static std::string GetAppId(const std::string& package_id);
+ static std::string GetExecPath(const std::string& app_id);
+ static std::string GetApplicationPath();
+
+ private:
+ void AddInternalStorage(const std::string& label, const std::string& path);
+ void AddStorage(int storage, storage_type_e type, storage_state_e state,
+ const std::string& path);
+ void NotifyStorageStateChanged(int id, storage_state_e state);
+ static bool OnStorageDeviceSupported(int id, storage_type_e type,
+ storage_state_e state, const char* path, void* user_data);
+ static void OnStorageStateChanged(int id, storage_state_e state,
+ void* user_data);
+
+ CallBackFunctionPtr storage_changed_cb_;
+ void* cb_user_data_;
+
+ typedef std::pair<std::string, Storage> StorageLabelPair;
+ Storages storages_;
+ std::vector<int> watched_storages_;
+};
+
+#endif // COMMON_VIRTUAL_FS_H_
diff --git a/xwalk/generate_api.py b/xwalk/generate_api.py
new file mode 100755
index 00000000..cef97b7a
--- /dev/null
+++ b/xwalk/generate_api.py
@@ -0,0 +1,19 @@
+# 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
+
+TEMPLATE = """\
+extern const char %s[];
+const char %s[] = { %s, 0 };
+"""
+
+js_code = sys.argv[1]
+lines = file(js_code).read()
+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/xwalk/vehicle.cc b/xwalk/vehicle.cc
new file mode 100644
index 00000000..3eda44ef
--- /dev/null
+++ b/xwalk/vehicle.cc
@@ -0,0 +1,711 @@
+// Copyright (c) 2014 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.
+
+#include "vehicle.h"
+
+#include <abstractpropertytype.h>
+#include <debugout.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <listplusplus.h>
+#include <superptr.hpp>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+common::Instance* Vehicle::CallbackInfo::instance = nullptr;
+
+namespace {
+const char* amb_service = "org.automotive.message.broker";
+const char* prop_iface = "org.freedesktop.DBus.Properties";
+
+const char* vehicle_error_permission_denied = "permission_denied";
+const char* vehicle_error_invalid_operation = "invalid_operation";
+const char* vehicle_error_timeout = "timeout";
+const char* vehicle_error_invalid_zone = "invalid_zone";
+const char* vehicle_error_unknown = "unknown";
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones);
+picojson::value::array AmbZoneToW3C(int amb_zone);
+
+template<typename T> unique_ptr<T> make_unique(T* t) {
+ return unique_ptr<T>(t);
+}
+
+void PostReply(Vehicle::CallbackInfo* cb_obj, picojson::value object) {
+ DebugOut() << "Posting reply" << endl;
+ picojson::object msg;
+
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["asyncCallId"] = picojson::value(cb_obj->callback_id);
+ msg["value"] = object;
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+void PostError(Vehicle::CallbackInfo* cb_obj, const std::string& error) {
+ picojson::object msg;
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["error"] = picojson::value(true);
+ msg["value"] = picojson::value(error);
+ msg["asyncCallId"] =
+ picojson::value(static_cast<double>(cb_obj->callback_id));
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Error Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+picojson::value GetBasic(GVariant* value) {
+ std::string type = g_variant_get_type_string(value);
+ picojson::value v;
+
+ if (type == "i") {
+ v = picojson::value(static_cast<double>(GVS<int>::value(value)));
+ } else if (type == "d") {
+ v = picojson::value(GVS<double>::value(value));
+ } else if (type == "q") {
+ v = picojson::value(static_cast<double>(GVS<uint16_t>::value(value)));
+ } else if (type == "n") {
+ v = picojson::value(static_cast<double>(GVS<int16_t>::value(value)));
+ } else if (type == "y") {
+ v = picojson::value(static_cast<double>(GVS<char>::value(value)));
+ } else if (type == "u") {
+ v = picojson::value(static_cast<double>(GVS<uint32_t>::value(value)));
+ } else if (type == "x") {
+ v = picojson::value(static_cast<double>(GVS<int64_t>::value(value)));
+ } else if (type == "t") {
+ v = picojson::value(static_cast<double>(GVS<uint64_t>::value(value)));
+ } else if (type == "b") {
+ v = picojson::value(GVS<bool>::value(value));
+ } else if (type == "s") {
+ v = picojson::value(g_variant_get_string(value, nullptr));
+ }
+
+ return v;
+}
+
+GVariant* GetBasic(picojson::value value, const std::string& type) {
+ GVariant* v = nullptr;
+
+ if (type == "i") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "d") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "q") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "n") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "y") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "u") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "x") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "t") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "b") {
+ v = g_variant_new(type.c_str(), value.get<bool>());
+ } else if (type == "s") {
+ v = g_variant_new(type.c_str(), value.get<std::string>().c_str());
+ }
+
+ return v;
+}
+
+void AsyncGetCallback(GObject* source, GAsyncResult* res, gpointer user_data) {
+ debugOut("GetAll() method call completed");
+
+ Vehicle::CallbackInfo *cb_obj =
+ static_cast<Vehicle::CallbackInfo*>(user_data);
+
+ auto cb_obj_ptr = make_unique(cb_obj);
+
+ if (!cb_obj_ptr) {
+ debugOut("invalid cb object");
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto property_map = amb::make_super(
+ g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "failed to call GetAll on interface: "
+ << error_ptr->message << endl;
+ PostError(cb_obj_ptr.get(), "unknown");
+ return;
+ }
+
+ GVariantIter* iter;
+ gchar* key;
+ GVariant* value;
+
+ g_variant_get(property_map.get(), "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ picojson::value::object object;
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string temp_key = key_ptr.get();
+
+ std::transform(temp_key.begin(), temp_key.begin() + 1,
+ temp_key.begin(), ::tolower);
+
+ object[temp_key] = GetBasic(value_ptr.get());
+
+ if (temp_key == "zone") {
+ object[temp_key] =
+ picojson::value(AmbZoneToW3C(object[temp_key].get<double>()));
+ }
+ }
+
+ PostReply(cb_obj_ptr.get(), picojson::value(object));
+}
+
+picojson::value::array AmbZoneToW3C(int amb_zone) {
+ picojson::value::array z;
+
+ if (amb_zone & Zone::Left) {
+ z.push_back(picojson::value("Left"));
+ }
+ if (amb_zone & Zone::Right) {
+ z.push_back(picojson::value("Right"));
+ }
+ if (amb_zone & Zone::Front) {
+ z.push_back(picojson::value("Front"));
+ }
+ if (amb_zone & Zone::Middle) {
+ z.push_back(picojson::value("Middle"));
+ }
+ if (amb_zone & Zone::Center) {
+ z.push_back(picojson::value("Center"));
+ }
+ if (amb_zone & Zone::Rear) {
+ z.push_back(picojson::value("Rear"));
+ }
+
+ return z;
+}
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones) {
+ picojson::value::array zones;
+
+ for (auto i : amb_zones) {
+ zones.push_back(picojson::value(AmbZoneToW3C(i)));
+ }
+
+ return zones;
+}
+
+static void SignalCallback(GDBusConnection* connection,
+ const gchar*,
+ const gchar* object_path,
+ const gchar*,
+ const gchar*,
+ GVariant* parameters,
+ gpointer user_data) {
+ DebugOut() << "Got signal" << endl;
+ std::vector<ObjectZone*> amb_objects_ =
+ *(static_cast<std::vector<ObjectZone*>*>(user_data));
+
+ GVariant* value_array;
+ GVariant* iface_name;
+ GVariant* invalidated;
+
+ g_variant_get(parameters,
+ "(&s@a{sv}^a&s)",
+ &iface_name,
+ &value_array,
+ &invalidated);
+
+ GVariantIter iter;
+
+ g_variant_iter_init(&iter, value_array);
+
+ ObjectZone* object = nullptr;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ object = i;
+ }
+ }
+
+ if (!object) {
+ DebugOut(DebugOut::Error) << "received signal for which "
+ << "we have no corresponding amb object" << endl;
+ return;
+ }
+
+ char* key;
+ GVariant* value;
+
+ while (g_variant_iter_next(&iter, "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+
+ if (tempkey == "zone") {
+ object->value[tempkey] =
+ picojson::value(AmbZoneToW3C(object->value[tempkey].get<double>()));
+ }
+ }
+
+ object->value["interfaceName"] = picojson::value(object->name);
+
+ Vehicle::CallbackInfo call;
+ call.method = "subscribe";
+ call.callback_id = -1;
+
+ PostReply(&call, picojson::value(object->value));
+}
+
+} // namespace
+
+Vehicle::Vehicle(common::Instance* instance)
+ : main_loop_(g_main_loop_new(0, FALSE)),
+ thread_(Vehicle::SetupMainloop, this),
+ instance_(instance) {
+ CallbackInfo::instance = instance_;
+ thread_.detach();
+}
+
+Vehicle::~Vehicle() {
+ g_main_loop_quit(main_loop_);
+ g_main_loop_unref(main_loop_);
+
+ for (auto i : amb_objects_) {
+ delete i;
+ }
+}
+
+void Vehicle::Get(const std::string& property, Zone::Type zone, double ret_id) {
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "get";
+ data->instance = instance_;
+
+
+ std::string find_error;
+ std::string obj_pstr = FindProperty(property, zone, find_error);
+
+ if (obj_pstr.empty()) {
+ debugOut("could not find property " + property);
+ PostError(data, find_error);
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto properties_proxy = amb::make_super(
+ g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ obj_pstr.c_str(),
+ prop_iface,
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to get properties proxy: " << error->message << endl;
+ return;
+ }
+
+ std::string interfaceName = "org.automotive." + property;
+
+ g_dbus_proxy_call(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interfaceName.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ AsyncGetCallback, data);
+}
+
+void Vehicle::GetZones(const std::string& object_name, double ret_id) {
+ auto manager_proxy = amb::make_super(GetAutomotiveManager());
+
+ if (!manager_proxy) {
+ return;
+ }
+
+ GError* error(nullptr);
+
+ auto zones_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy.get(),
+ "ZonesForObjectName",
+ g_variant_new("(s)",
+ object_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "error calling ZonesForObjectName: "
+ << error_ptr->message << endl;
+ return;
+ }
+
+ if (!zones_variant) {
+ DebugOut() << "Invalid response from ZonesForObjectName " << endl;
+ return;
+ }
+
+ GVariantIter* iter(nullptr);
+
+ g_variant_get(zones_variant.get(), "(ai)", &iter);
+
+ if (!iter) {
+ DebugOut() << "No zones for object " << object_name << endl;
+ return;
+ }
+
+ auto iter_ptr = amb::make_super(iter);
+
+ std::vector<int> zones_array;
+
+ GVariant* value(nullptr);
+
+ while ((value = g_variant_iter_next_value(iter_ptr.get()))) {
+ auto value_ptr = amb::make_super(value);
+ int v = 0;
+
+ g_variant_get(value_ptr.get(), "(i)", &v);
+ zones_array.push_back(v);
+ }
+
+ picojson::value::array w3c_zones = AmbZoneToW3C(zones_array);
+
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "zones";
+ data->instance = instance_;
+
+ PostReply(data, picojson::value(w3c_zones));
+}
+
+std::string Vehicle::FindProperty(const std::string& object_name, int zone, std::string& error_str) {
+ GDBusProxy* manager_proxy = GetAutomotiveManager();
+
+ if (!manager_proxy) {
+ return "";
+ }
+
+ GError* error(nullptr);
+
+ auto object_path_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy,
+ "FindObjectForZone",
+ g_variant_new("(si)",
+ object_name.c_str(),
+ zone),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "error calling FindObjectForZone: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ return "";
+ }
+
+ if (!object_path_variant) {
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ return "";
+ }
+
+ gchar* obj_path = nullptr;
+ g_variant_get(object_path_variant.get(), "(o)", &obj_path);
+
+ auto obj_path_ptr = amb::make_super(obj_path);
+
+ DebugOut() << "FindObjectForZone() returned object path: "
+ << obj_path_ptr.get() << endl;
+
+ return obj_path;
+}
+
+GDBusProxy* Vehicle::GetAutomotiveManager() {
+ if (manager_proxy_)
+ return manager_proxy_.get();
+
+ GError* error = nullptr;
+ manager_proxy_ = amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ "/",
+ "org.automotive.Manager",
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "error calling GetAutomotiveManager: "
+ << error_ptr->message << endl;
+ }
+
+ return manager_proxy_.get();
+}
+
+void Vehicle::SetupMainloop(void* data) {
+ Vehicle* self = reinterpret_cast<Vehicle*>(data);
+ GMainContext* ctx = g_main_context_default();
+
+ g_main_context_push_thread_default(ctx);
+ g_main_loop_run(self->main_loop_);
+}
+
+
+void Vehicle::Subscribe(const std::string& object_name, Zone::Type zone) {
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ if (object_path.empty()) {
+ DebugOut() << "Error FindProperty failed for " << object_name;
+ return;
+ }
+
+ bool already_subscribed = false;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ already_subscribed = true;
+ break;
+ }
+ }
+
+ if (!already_subscribed) {
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut() << "error creating properties proxy: "
+ << proxy_error_ptr->message << endl;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ GError* get_all_error = nullptr;
+
+ GVariant* property_map =
+ g_dbus_proxy_call_sync(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interface_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ &get_all_error);
+
+ auto get_all_error_ptr = amb::make_super(get_all_error);
+
+ if (get_all_error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to call GetAll on interface "
+ << interface_name << " "
+ << get_all_error_ptr->message << endl;
+ return;
+ }
+
+ GVariantIter* iter;
+
+ g_variant_get(property_map, "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ char* key;
+ GVariant* value;
+
+ ObjectZone* object = new ObjectZone(object_name, zone, object_path);
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+ }
+
+ object->handle =
+ g_dbus_connection_signal_subscribe(dbus_connection_.get(),
+ amb_service,
+ prop_iface,
+ "PropertiesChanged",
+ object_path.c_str(), NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ SignalCallback, &amb_objects_,
+ NULL);
+
+ amb_objects_.push_back(object);
+ } else {
+ DebugOut() << "Already subscribed to " << object_name << endl;
+ }
+}
+
+
+void Vehicle::Unsubscribe(const std::string& property, Zone::Type zone) {
+ std::vector<ObjectZone*> to_clean;
+
+ for (auto obj : amb_objects_) {
+ if (obj->name == property && obj->zone == zone) {
+ g_dbus_connection_signal_unsubscribe(dbus_connection_.get(),
+ obj->handle);
+ to_clean.push_back(obj);
+ }
+ }
+
+ for (auto obj : to_clean) {
+ removeOne(&amb_objects_, obj);
+ delete obj;
+ }
+}
+
+
+void Vehicle::Set(const std::string &object_name, picojson::object value,
+ Zone::Type zone, double ret_id)
+{
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ Vehicle::CallbackInfo callback;
+ callback.callback_id = ret_id;
+ callback.method = "set";
+ callback.instance = instance_;
+
+ if (object_path.empty() || !find_error.empty()) {
+ DebugOut(DebugOut::Error) << "Object not found. Check object Name and zone."
+ << object_name << std::endl;
+ PostError(&callback, find_error);
+ return;
+ }
+
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut(DebugOut::Error) << "Error creating property proxy for " << object_path << std::endl;
+ return;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ for (auto itr : value) {
+ GError* err = nullptr;
+ std::string attribute = itr.first;
+
+ std::transform(attribute.begin(), attribute.begin()+1, attribute.begin(), ::toupper);
+
+ auto var_value =
+ amb::make_super(g_dbus_proxy_call_sync(properties_proxy.get(),
+ "Get",
+ g_variant_new("(ss)",
+ interface_name.c_str(),
+ attribute.c_str()),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err));
+ auto err_ptr = amb::make_super(err);
+ if (err_ptr || !var_value) {
+ DebugOut(DebugOut::Error) << "Error getting initial property signature type: " <<
+ err_ptr->message << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* get_value = nullptr;
+ g_variant_get(var_value.get(), "(v)", &get_value);
+
+ auto get_value_ptr = amb::make_super(get_value);
+
+ if (!get_value_ptr) {
+ DebugOut(DebugOut::Error) << "Error getting variant value." << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* v = GetBasic(itr.second, g_variant_get_type_string(get_value_ptr.get()));
+
+ if (!v) {
+ DebugOut(DebugOut::Error) << "Error converting value to GVariant" << endl;
+ PostError(&callback, vehicle_error_unknown);
+ }
+
+ GError* set_error = nullptr;
+
+ g_dbus_proxy_call_sync(properties_proxy.get(), "Set",
+ g_variant_new("(ssv)",
+ interface_name.c_str(),
+ attribute.c_str(),
+ v),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &set_error);
+
+ auto set_error_ptr = amb::make_super(set_error);
+
+ if (set_error_ptr) {
+ DebugOut(DebugOut::Error) << "error setting property:" << set_error_ptr->message << endl;
+
+ if(set_error_ptr->code == G_IO_ERROR_PERMISSION_DENIED || std::string(g_dbus_error_get_remote_error(set_error_ptr.get())) == "org.freedesktop.DBus.Error.AccessDenied")
+ {
+ DebugOut(DebugOut::Error) << "permission denied" << endl;
+ PostError(&callback, vehicle_error_permission_denied);
+ }
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+ }
+
+ PostReply(&callback, picojson::value());
+}
diff --git a/xwalk/vehicle.h b/xwalk/vehicle.h
new file mode 100644
index 00000000..63eebd43
--- /dev/null
+++ b/xwalk/vehicle.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2014 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.
+
+#ifndef VEHICLE_VEHICLE_H_
+#define VEHICLE_VEHICLE_H_
+
+#include <abstractpropertytype.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <superptr.hpp>
+
+#include <string>
+#include <thread> // NOLINT
+#include <vector>
+
+#include "common/picojson.h"
+
+namespace common {
+
+class Instance;
+
+} // namespace common
+
+struct ObjectZone {
+ ObjectZone():zone(0) {}
+
+ ObjectZone(const std::string& o, int z, const std::string& op)
+ : name(o), zone(z), object_path(op) {}
+
+ ObjectZone(const ObjectZone& other)
+ : name(other.name), zone(other.zone), object_path(other.object_path) {}
+
+ std::string name;
+ int zone;
+ uint handle;
+
+ std::string object_path;
+
+ bool operator ==(const ObjectZone& other) const {
+ return object_path == other.object_path;
+ }
+
+ picojson::object value;
+};
+
+struct ObjectZoneCompare {
+ bool operator() (const ObjectZone& lhs, const ObjectZone& rhs) {
+ return (lhs.name == rhs.name && lhs.zone < rhs.zone) ||
+ (lhs.name < rhs.name);
+ }
+};
+
+typedef std::function<void (picojson::object)> GetReply;
+typedef std::function<void (std::string)> ErrorReply;
+
+class Vehicle {
+ public:
+ struct CallbackInfo {
+ std::string method;
+ static common::Instance* instance;
+ double callback_id;
+ };
+
+ explicit Vehicle(common::Instance* i);
+ ~Vehicle();
+
+ void Get(const std::string& property, Zone::Type zone, double ret_id);
+ void GetZones(const std::string& property, double ret_id);
+ void Subscribe(const std::string& property, Zone::Type zone);
+ void Unsubscribe(const std::string& property, Zone::Type zone);
+ void Set(const std::string& property, picojson::object value, Zone::Type zone, double ret_id);
+
+ private:
+ std::string FindProperty(const std::string& object_name, int zone, string &error_str);
+ GDBusProxy* GetAutomotiveManager();
+
+ static void SetupMainloop(void* data);
+ GMainLoop* main_loop_;
+ std::thread thread_;
+ common::Instance* instance_;
+
+ std::vector<ObjectZone*> amb_objects_;
+
+ amb::super_ptr<GDBusProxy> manager_proxy_;
+ amb::super_ptr<GDBusConnection> dbus_connection_;
+};
+
+#endif // VEHICLE_VEHICLE_H_
diff --git a/xwalk/vehicle.html b/xwalk/vehicle.html
new file mode 100644
index 00000000..b4eecf7c
--- /dev/null
+++ b/xwalk/vehicle.html
@@ -0,0 +1,61 @@
+<html>
+<h1>Hello,Vehicle API!</h1>
+
+<body>
+<pre id="console"></pre>
+<script>
+
+function debug(stuff) {
+ console.log(stuff);
+}
+
+vehicle = navigator.vehicle;
+
+debug('vehicle.vehicleSpeed ' + vehicle.vehicleSpeed);
+
+var zone = new Zone;
+
+console.log('Driver zone: ' + zone.driver.value);
+
+var zone1 = new Zone(["Front", "Left"]);
+var zone2 = new Zone(["Left", "Front"]);
+var zone3 = new Zone(["Front", "Right"]);
+var zone4 = new Zone([]);
+
+debug("zone1 == zone2 ? " + zone1.equals(zone2));
+debug("zone1 == zone3 ? " + zone1.equals(zone3));
+debug("zone1 == zone1 ? " + zone1.equals(zone1));
+debug("zone1 == empty zone ? " + zone1.equals(zone4));
+
+vehicle.vehicleSpeed.get().then(function(vehicleSpeed) {
+ try {
+ console.log("vehicle speed " + JSON.stringify(vehicleSpeed));
+ debug("Vehicle speed: " + vehicleSpeed.speed);
+ } catch(error) {
+ console.log("error " + error.message);
+ }
+},
+function(error) {
+ debug("There was an error");
+});
+
+//test subscribe:
+var subReplies = 0;
+var handle = vehicle.vehicleSpeed.subscribe(function(data) {
+ console.log("got subscribe callback");
+ debug("Vehicle speed changed: " + data.speed);
+ subReplies++;
+
+ if (subReplies === 5) {
+ debug("unsubscribing");
+ vehicle.vehicleSpeed.unsubscribe(handle);
+ }
+});
+
+//test errors:
+vehicle.vehicleSpeed.get("invalidzone").then(function() { },
+ function(error) { debug("Invalid zone: " + error.message); });
+
+</script>
+</body>
+</html>
diff --git a/xwalk/vehicle_api.cc b/xwalk/vehicle_api.cc
new file mode 100644
index 00000000..aaeb6a06
--- /dev/null
+++ b/xwalk/vehicle_api.cc
@@ -0,0 +1,2 @@
+extern const char kSource_vehicle_api[];
+const char kSource_vehicle_api[] = { 47, 47, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 99, 41, 32, 50, 48, 49, 52, 32, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 46, 32, 65, 108, 108, 32, 114, 105, 103, 104, 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 10, 47, 47, 32, 85, 115, 101, 32, 111, 102, 32, 116, 104, 105, 115, 32, 115, 111, 117, 114, 99, 101, 32, 99, 111, 100, 101, 32, 105, 115, 32, 103, 111, 118, 101, 114, 110, 101, 100, 32, 98, 121, 32, 97, 32, 66, 83, 68, 45, 115, 116, 121, 108, 101, 32, 108, 105, 99, 101, 110, 115, 101, 32, 116, 104, 97, 116, 32, 99, 97, 110, 32, 98, 101, 10, 47, 47, 32, 102, 111, 117, 110, 100, 32, 105, 110, 32, 116, 104, 101, 32, 76, 73, 67, 69, 78, 83, 69, 32, 102, 105, 108, 101, 46, 10, 10, 118, 97, 114, 32, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 32, 61, 32, 48, 59, 10, 118, 97, 114, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 32, 61, 32, 123, 125, 59, 10, 10, 118, 97, 114, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 32, 61, 32, 91, 93, 59, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 118, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 67, 111, 109, 109, 111, 110, 67, 111, 110, 116, 114, 117, 99, 116, 111, 114, 40, 111, 98, 106, 44, 32, 97, 116, 116, 110, 97, 109, 101, 41, 32, 123, 10, 32, 32, 111, 98, 106, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 32, 61, 32, 97, 116, 116, 110, 97, 109, 101, 59, 10, 10, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 123, 125, 59, 10, 32, 32, 109, 115, 103, 91, 39, 109, 101, 116, 104, 111, 100, 39, 93, 32, 61, 32, 39, 122, 111, 110, 101, 115, 39, 59, 10, 32, 32, 109, 115, 103, 91, 39, 110, 97, 109, 101, 39, 93, 32, 61, 32, 111, 98, 106, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 59, 10, 10, 32, 32, 111, 98, 106, 46, 95, 122, 111, 110, 101, 115, 32, 61, 32, 110, 101, 119, 32, 90, 111, 110, 101, 59, 10, 10, 32, 32, 118, 97, 114, 32, 99, 97, 108, 108, 32, 61, 32, 110, 101, 119, 32, 65, 115, 121, 110, 99, 67, 97, 108, 108, 40, 102, 117, 110, 99, 116, 105, 111, 110, 40, 100, 97, 116, 97, 41, 32, 123, 10, 32, 32, 32, 32, 111, 98, 106, 46, 95, 122, 111, 110, 101, 115, 32, 61, 32, 100, 97, 116, 97, 59, 10, 32, 32, 125, 41, 59, 10, 10, 32, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 93, 32, 61, 32, 99, 97, 108, 108, 59, 10, 32, 32, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 32, 61, 32, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 59, 10, 32, 32, 43, 43, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 59, 10, 10, 32, 32, 101, 120, 116, 101, 110, 115, 105, 111, 110, 46, 112, 111, 115, 116, 77, 101, 115, 115, 97, 103, 101, 40, 74, 83, 79, 78, 46, 115, 116, 114, 105, 110, 103, 105, 102, 121, 40, 109, 115, 103, 41, 41, 59, 10, 10, 32, 32, 79, 98, 106, 101, 99, 116, 46, 100, 101, 102, 105, 110, 101, 80, 114, 111, 112, 101, 114, 116, 121, 40, 111, 98, 106, 44, 32, 39, 122, 111, 110, 101, 115, 39, 44, 32, 123, 32, 103, 101, 116, 58, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 32, 123, 32, 114, 101, 116, 117, 114, 110, 32, 111, 98, 106, 46, 95, 122, 111, 110, 101, 115, 32, 125, 32, 125, 41, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 86, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 40, 97, 116, 116, 110, 97, 109, 101, 41, 32, 123, 10, 32, 32, 118, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 67, 111, 109, 109, 111, 110, 67, 111, 110, 116, 114, 117, 99, 116, 111, 114, 40, 116, 104, 105, 115, 44, 32, 97, 116, 116, 110, 97, 109, 101, 41, 59, 10, 125, 10, 10, 86, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46, 103, 101, 116, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 122, 111, 110, 101, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 123, 125, 59, 10, 32, 32, 109, 115, 103, 91, 39, 109, 101, 116, 104, 111, 100, 39, 93, 32, 61, 32, 39, 103, 101, 116, 39, 59, 10, 32, 32, 109, 115, 103, 91, 39, 110, 97, 109, 101, 39, 93, 32, 61, 32, 116, 104, 105, 115, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 59, 10, 32, 32, 109, 115, 103, 91, 39, 122, 111, 110, 101, 39, 93, 32, 61, 32, 122, 111, 110, 101, 59, 10, 10, 32, 32, 114, 101, 116, 117, 114, 110, 32, 99, 114, 101, 97, 116, 101, 80, 114, 111, 109, 105, 115, 101, 40, 109, 115, 103, 41, 59, 10, 125, 59, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 40, 97, 116, 116, 110, 97, 109, 101, 41, 32, 123, 10, 32, 32, 118, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 67, 111, 109, 109, 111, 110, 67, 111, 110, 116, 114, 117, 99, 116, 111, 114, 40, 116, 104, 105, 115, 44, 32, 97, 116, 116, 110, 97, 109, 101, 41, 59, 10, 125, 10, 10, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 32, 61, 32, 86, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 59, 10, 10, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46, 115, 117, 98, 115, 99, 114, 105, 98, 101, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 99, 97, 108, 108, 98, 97, 99, 107, 44, 32, 122, 111, 110, 101, 41, 32, 123, 10, 32, 32, 105, 102, 32, 40, 33, 122, 111, 110, 101, 41, 32, 122, 111, 110, 101, 32, 61, 32, 110, 101, 119, 32, 90, 111, 110, 101, 40, 41, 59, 10, 10, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 123, 125, 59, 10, 32, 32, 109, 115, 103, 91, 39, 109, 101, 116, 104, 111, 100, 39, 93, 32, 61, 32, 39, 115, 117, 98, 115, 99, 114, 105, 98, 101, 39, 59, 10, 32, 32, 109, 115, 103, 91, 39, 110, 97, 109, 101, 39, 93, 32, 61, 32, 116, 104, 105, 115, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 59, 10, 32, 32, 109, 115, 103, 91, 39, 122, 111, 110, 101, 39, 93, 32, 61, 32, 122, 111, 110, 101, 59, 10, 10, 32, 32, 101, 120, 116, 101, 110, 115, 105, 111, 110, 46, 112, 111, 115, 116, 77, 101, 115, 115, 97, 103, 101, 40, 74, 83, 79, 78, 46, 115, 116, 114, 105, 110, 103, 105, 102, 121, 40, 109, 115, 103, 41, 41, 59, 10, 10, 32, 32, 109, 115, 103, 91, 39, 99, 97, 108, 108, 98, 97, 99, 107, 39, 93, 32, 61, 32, 99, 97, 108, 108, 98, 97, 99, 107, 59, 10, 10, 32, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 46, 112, 117, 115, 104, 40, 109, 115, 103, 41, 59, 10, 10, 32, 32, 114, 101, 116, 117, 114, 110, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 46, 108, 101, 110, 103, 116, 104, 32, 45, 32, 49, 59, 10, 125, 59, 10, 10, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46, 117, 110, 115, 117, 98, 115, 99, 114, 105, 98, 101, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 104, 97, 110, 100, 108, 101, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 111, 98, 106, 32, 61, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 91, 104, 97, 110, 100, 108, 101, 93, 59, 10, 32, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 46, 115, 112, 108, 105, 99, 101, 40, 104, 97, 110, 100, 108, 101, 44, 32, 49, 41, 59, 10, 10, 32, 32, 118, 97, 114, 32, 117, 110, 115, 117, 98, 115, 99, 114, 105, 98, 101, 32, 61, 32, 116, 114, 117, 101, 59, 10, 10, 32, 32, 102, 111, 114, 32, 40, 118, 97, 114, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32, 60, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 46, 108, 101, 110, 103, 116, 104, 59, 32, 105, 43, 43, 41, 32, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 116, 101, 115, 116, 79, 98, 106, 32, 61, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 91, 105, 93, 59, 10, 10, 32, 32, 32, 32, 105, 102, 32, 40, 116, 101, 115, 116, 79, 98, 106, 46, 110, 97, 109, 101, 32, 61, 61, 61, 32, 111, 98, 106, 46, 110, 97, 109, 101, 32, 38, 38, 32, 116, 101, 115, 116, 79, 98, 106, 46, 122, 111, 110, 101, 46, 101, 113, 117, 97, 108, 115, 40, 111, 98, 106, 46, 122, 111, 110, 101, 41, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 117, 110, 115, 117, 98, 115, 99, 114, 105, 98, 101, 32, 61, 32, 102, 97, 108, 115, 101, 59, 10, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 125, 10, 32, 32, 125, 10, 10, 32, 32, 105, 102, 32, 40, 117, 110, 115, 117, 98, 115, 99, 114, 105, 98, 101, 41, 32, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 123, 125, 59, 10, 32, 32, 32, 32, 109, 115, 103, 91, 39, 109, 101, 116, 104, 111, 100, 39, 93, 32, 61, 32, 39, 117, 110, 115, 117, 98, 115, 99, 114, 105, 98, 101, 39, 59, 10, 32, 32, 32, 32, 109, 115, 103, 91, 39, 110, 97, 109, 101, 39, 93, 32, 61, 32, 116, 104, 105, 115, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 59, 10, 32, 32, 32, 32, 109, 115, 103, 91, 39, 122, 111, 110, 101, 39, 93, 32, 61, 32, 111, 98, 106, 46, 122, 111, 110, 101, 59, 10, 10, 32, 32, 32, 32, 101, 120, 116, 101, 110, 115, 105, 111, 110, 46, 112, 111, 115, 116, 77, 101, 115, 115, 97, 103, 101, 40, 74, 83, 79, 78, 46, 115, 116, 114, 105, 110, 103, 105, 102, 121, 40, 109, 115, 103, 41, 41, 59, 10, 32, 32, 125, 10, 125, 59, 10, 10, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46, 115, 101, 116, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 32, 40, 118, 97, 108, 117, 101, 44, 32, 122, 111, 110, 101, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 123, 125, 59, 10, 32, 32, 109, 115, 103, 91, 39, 109, 101, 116, 104, 111, 100, 39, 93, 32, 61, 32, 39, 115, 101, 116, 39, 59, 10, 32, 32, 109, 115, 103, 91, 39, 110, 97, 109, 101, 39, 93, 32, 61, 32, 116, 104, 105, 115, 46, 97, 116, 116, 114, 105, 98, 117, 116, 101, 78, 97, 109, 101, 59, 10, 32, 32, 109, 115, 103, 91, 39, 122, 111, 110, 101, 39, 93, 32, 61, 32, 122, 111, 110, 101, 59, 10, 32, 32, 109, 115, 103, 91, 39, 118, 97, 108, 117, 101, 39, 93, 32, 61, 32, 118, 97, 108, 117, 101, 59, 10, 10, 32, 32, 114, 101, 116, 117, 114, 110, 32, 99, 114, 101, 97, 116, 101, 80, 114, 111, 109, 105, 115, 101, 40, 109, 115, 103, 41, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 65, 115, 121, 110, 99, 67, 97, 108, 108, 40, 114, 101, 115, 111, 108, 118, 101, 44, 32, 114, 101, 106, 101, 99, 116, 41, 32, 123, 10, 32, 32, 116, 104, 105, 115, 46, 114, 101, 115, 111, 108, 118, 101, 32, 61, 32, 114, 101, 115, 111, 108, 118, 101, 59, 10, 32, 32, 116, 104, 105, 115, 46, 114, 101, 106, 101, 99, 116, 32, 61, 32, 114, 101, 106, 101, 99, 116, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 99, 114, 101, 97, 116, 101, 80, 114, 111, 109, 105, 115, 101, 40, 109, 115, 103, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 112, 114, 111, 109, 105, 115, 101, 32, 61, 32, 110, 101, 119, 32, 80, 114, 111, 109, 105, 115, 101, 40, 102, 117, 110, 99, 116, 105, 111, 110, 40, 114, 101, 115, 111, 108, 118, 101, 44, 32, 114, 101, 106, 101, 99, 116, 41, 32, 123, 10, 32, 32, 32, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 93, 32, 61, 32, 110, 101, 119, 32, 65, 115, 121, 110, 99, 67, 97, 108, 108, 40, 114, 101, 115, 111, 108, 118, 101, 44, 32, 114, 101, 106, 101, 99, 116, 41, 59, 10, 32, 32, 125, 41, 59, 10, 10, 32, 32, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 32, 61, 32, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 59, 10, 32, 32, 101, 120, 116, 101, 110, 115, 105, 111, 110, 46, 112, 111, 115, 116, 77, 101, 115, 115, 97, 103, 101, 40, 74, 83, 79, 78, 46, 115, 116, 114, 105, 110, 103, 105, 102, 121, 40, 109, 115, 103, 41, 41, 59, 10, 32, 32, 43, 43, 110, 101, 120, 116, 95, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 95, 105, 100, 59, 10, 32, 32, 114, 101, 116, 117, 114, 110, 32, 112, 114, 111, 109, 105, 115, 101, 59, 10, 125, 10, 10, 119, 105, 110, 100, 111, 119, 46, 90, 111, 110, 101, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 122, 111, 110, 101, 41, 32, 123, 10, 32, 32, 116, 104, 105, 115, 46, 118, 97, 108, 117, 101, 32, 61, 32, 122, 111, 110, 101, 32, 63, 32, 122, 111, 110, 101, 32, 58, 32, 91, 93, 59, 10, 10, 32, 32, 79, 98, 106, 101, 99, 116, 46, 100, 101, 102, 105, 110, 101, 80, 114, 111, 112, 101, 114, 116, 121, 40, 116, 104, 105, 115, 44, 32, 39, 100, 114, 105, 118, 101, 114, 39, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 32, 101, 110, 117, 109, 101, 114, 97, 98, 108, 101, 58, 32, 102, 97, 108, 115, 101, 44, 32, 103, 101, 116, 58, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 114, 101, 116, 117, 114, 110, 32, 110, 101, 119, 32, 90, 111, 110, 101, 40, 91, 39, 70, 114, 111, 110, 116, 39, 44, 32, 39, 76, 101, 102, 116, 39, 93, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 32, 125, 41, 59, 10, 125, 59, 10, 10, 119, 105, 110, 100, 111, 119, 46, 90, 111, 110, 101, 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46, 101, 113, 117, 97, 108, 115, 32, 61, 32, 102, 117, 110, 99, 116, 105, 111, 110, 40, 122, 111, 110, 101, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 105, 115, 95, 101, 113, 117, 97, 108, 32, 61, 32, 116, 114, 117, 101, 59, 10, 10, 32, 32, 102, 111, 114, 32, 40, 118, 97, 114, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32, 60, 32, 122, 111, 110, 101, 46, 118, 97, 108, 117, 101, 46, 108, 101, 110, 103, 116, 104, 59, 32, 105, 43, 43, 41, 32, 123, 10, 32, 32, 32, 32, 105, 115, 95, 101, 113, 117, 97, 108, 32, 38, 61, 32, 116, 104, 105, 115, 46, 118, 97, 108, 117, 101, 46, 105, 110, 100, 101, 120, 79, 102, 40, 122, 111, 110, 101, 46, 118, 97, 108, 117, 101, 91, 105, 93, 41, 32, 33, 61, 61, 32, 45, 49, 59, 10, 32, 32, 125, 10, 10, 32, 32, 102, 111, 114, 32, 40, 118, 97, 114, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32, 60, 32, 116, 104, 105, 115, 46, 118, 97, 108, 117, 101, 46, 108, 101, 110, 103, 116, 104, 59, 32, 105, 43, 43, 41, 32, 123, 10, 32, 32, 32, 32, 105, 115, 95, 101, 113, 117, 97, 108, 32, 38, 61, 32, 122, 111, 110, 101, 46, 118, 97, 108, 117, 101, 46, 105, 110, 100, 101, 120, 79, 102, 40, 116, 104, 105, 115, 46, 118, 97, 108, 117, 101, 91, 105, 93, 41, 32, 33, 61, 61, 32, 45, 49, 59, 10, 32, 32, 125, 10, 10, 32, 32, 114, 101, 116, 117, 114, 110, 32, 105, 115, 95, 101, 113, 117, 97, 108, 59, 10, 125, 59, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 80, 114, 111, 112, 101, 114, 116, 121, 40, 111, 98, 106, 44, 32, 112, 114, 111, 112, 41, 32, 123, 10, 32, 32, 79, 98, 106, 101, 99, 116, 46, 100, 101, 102, 105, 110, 101, 80, 114, 111, 112, 101, 114, 116, 121, 40, 111, 98, 106, 44, 32, 112, 114, 111, 112, 44, 32, 123, 32, 101, 110, 117, 109, 101, 114, 97, 98, 108, 101, 58, 32, 116, 114, 117, 101, 44, 32, 118, 97, 108, 117, 101, 58, 32, 110, 101, 119, 32, 86, 101, 104, 105, 99, 108, 101, 73, 110, 116, 101, 114, 102, 97, 99, 101, 40, 112, 114, 111, 112, 41, 32, 125, 41, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 111, 98, 106, 44, 32, 112, 114, 111, 112, 41, 32, 123, 10, 32, 32, 79, 98, 106, 101, 99, 116, 46, 100, 101, 102, 105, 110, 101, 80, 114, 111, 112, 101, 114, 116, 121, 40, 111, 98, 106, 44, 32, 112, 114, 111, 112, 44, 32, 123, 32, 101, 110, 117, 109, 101, 114, 97, 98, 108, 101, 58, 32, 116, 114, 117, 101, 44, 32, 118, 97, 108, 117, 101, 58, 32, 110, 101, 119, 32, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 73, 110, 116, 101, 114, 102, 97, 99, 101, 40, 112, 114, 111, 112, 41, 32, 125, 41, 59, 10, 125, 10, 10, 101, 120, 116, 101, 110, 115, 105, 111, 110, 46, 115, 101, 116, 77, 101, 115, 115, 97, 103, 101, 76, 105, 115, 116, 101, 110, 101, 114, 40, 102, 117, 110, 99, 116, 105, 111, 110, 40, 106, 115, 111, 110, 41, 32, 123, 10, 32, 32, 116, 114, 121, 32, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 109, 115, 103, 32, 61, 32, 74, 83, 79, 78, 46, 112, 97, 114, 115, 101, 40, 106, 115, 111, 110, 41, 59, 10, 10, 32, 32, 32, 32, 115, 119, 105, 116, 99, 104, 32, 40, 109, 115, 103, 46, 109, 101, 116, 104, 111, 100, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 103, 101, 116, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 104, 97, 110, 100, 108, 101, 80, 114, 111, 109, 105, 115, 101, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 122, 111, 110, 101, 115, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 104, 97, 110, 100, 108, 101, 90, 111, 110, 101, 115, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 115, 117, 98, 115, 99, 114, 105, 98, 101, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 104, 97, 110, 100, 108, 101, 83, 117, 98, 115, 99, 114, 105, 98, 101, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 115, 101, 116, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 104, 97, 110, 100, 108, 101, 80, 114, 111, 109, 105, 115, 101, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 100, 101, 102, 97, 117, 108, 116, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 125, 10, 32, 32, 125, 32, 99, 97, 116, 99, 104, 32, 40, 101, 114, 114, 111, 114, 41, 32, 123, 10, 32, 32, 32, 32, 99, 111, 110, 115, 111, 108, 101, 46, 108, 111, 103, 40, 39, 69, 114, 114, 111, 114, 32, 105, 110, 32, 109, 101, 115, 115, 97, 103, 101, 32, 108, 105, 115, 116, 101, 110, 101, 114, 58, 32, 39, 32, 43, 32, 101, 114, 114, 111, 114, 41, 59, 10, 32, 32, 125, 10, 125, 41, 59, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 104, 97, 110, 100, 108, 101, 80, 114, 111, 109, 105, 115, 101, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 99, 98, 111, 98, 106, 32, 61, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 93, 59, 10, 10, 32, 32, 105, 102, 32, 40, 109, 115, 103, 46, 101, 114, 114, 111, 114, 41, 32, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 101, 114, 114, 111, 114, 32, 61, 32, 123, 125, 59, 10, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 101, 114, 114, 111, 114, 32, 61, 32, 109, 115, 103, 46, 118, 97, 108, 117, 101, 59, 10, 32, 32, 32, 32, 115, 119, 105, 116, 99, 104, 32, 40, 109, 115, 103, 46, 118, 97, 108, 117, 101, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, 95, 100, 101, 110, 105, 101, 100, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 109, 101, 115, 115, 97, 103, 101, 32, 61, 32, 39, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 32, 100, 101, 110, 105, 101, 100, 39, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 105, 110, 118, 97, 108, 105, 100, 95, 111, 112, 101, 114, 97, 116, 105, 111, 110, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 109, 101, 115, 115, 97, 103, 101, 32, 61, 32, 39, 73, 110, 118, 97, 108, 105, 100, 32, 111, 112, 101, 114, 97, 116, 105, 111, 110, 39, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 116, 105, 109, 101, 111, 117, 116, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 109, 101, 115, 115, 97, 103, 101, 32, 61, 32, 39, 79, 112, 101, 114, 97, 116, 105, 111, 110, 32, 116, 105, 109, 101, 100, 32, 111, 117, 116, 39, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 105, 110, 118, 97, 108, 105, 100, 95, 122, 111, 110, 101, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 109, 101, 115, 115, 97, 103, 101, 32, 61, 32, 39, 90, 111, 110, 101, 32, 105, 110, 118, 97, 108, 105, 100, 32, 111, 114, 32, 110, 111, 116, 32, 102, 111, 117, 110, 100, 39, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 99, 97, 115, 101, 32, 39, 117, 110, 107, 110, 111, 119, 110, 39, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 101, 114, 114, 111, 114, 46, 109, 101, 115, 115, 97, 103, 101, 32, 61, 32, 39, 65, 110, 32, 117, 110, 107, 110, 111, 119, 110, 32, 101, 114, 114, 111, 114, 32, 111, 99, 99, 117, 114, 101, 100, 39, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 32, 32, 100, 101, 102, 97, 117, 108, 116, 58, 10, 32, 32, 32, 32, 32, 32, 32, 32, 98, 114, 101, 97, 107, 59, 10, 32, 32, 32, 32, 125, 10, 10, 32, 32, 32, 32, 99, 98, 111, 98, 106, 46, 114, 101, 106, 101, 99, 116, 40, 101, 114, 114, 111, 114, 41, 59, 10, 32, 32, 125, 32, 101, 108, 115, 101, 32, 123, 10, 32, 32, 32, 32, 99, 98, 111, 98, 106, 46, 114, 101, 115, 111, 108, 118, 101, 40, 109, 115, 103, 46, 118, 97, 108, 117, 101, 41, 59, 10, 32, 32, 125, 10, 10, 32, 32, 100, 101, 108, 101, 116, 101, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 93, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 104, 97, 110, 100, 108, 101, 90, 111, 110, 101, 115, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 32, 123, 10, 32, 32, 118, 97, 114, 32, 99, 98, 111, 98, 106, 32, 61, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 93, 59, 10, 10, 32, 32, 105, 102, 32, 40, 99, 98, 111, 98, 106, 41, 10, 32, 32, 32, 32, 99, 98, 111, 98, 106, 46, 114, 101, 115, 111, 108, 118, 101, 40, 110, 101, 119, 32, 90, 111, 110, 101, 40, 109, 115, 103, 46, 118, 97, 108, 117, 101, 41, 41, 59, 10, 125, 10, 10, 102, 117, 110, 99, 116, 105, 111, 110, 32, 104, 97, 110, 100, 108, 101, 83, 117, 98, 115, 99, 114, 105, 98, 101, 82, 101, 112, 108, 121, 40, 109, 115, 103, 41, 32, 123, 10, 32, 32, 100, 101, 108, 101, 116, 101, 32, 97, 115, 121, 110, 99, 95, 99, 97, 108, 108, 115, 91, 109, 115, 103, 46, 97, 115, 121, 110, 99, 67, 97, 108, 108, 73, 100, 93, 59, 10, 32, 32, 118, 97, 114, 32, 118, 97, 108, 117, 101, 32, 61, 32, 109, 115, 103, 46, 118, 97, 108, 117, 101, 59, 10, 32, 32, 118, 97, 108, 117, 101, 46, 122, 111, 110, 101, 32, 61, 32, 110, 101, 119, 32, 90, 111, 110, 101, 40, 118, 97, 108, 117, 101, 46, 122, 111, 110, 101, 41, 59, 10, 10, 32, 32, 102, 111, 114, 32, 40, 118, 97, 114, 32, 105, 32, 61, 32, 48, 59, 32, 105, 32, 60, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 46, 108, 101, 110, 103, 116, 104, 59, 32, 105, 43, 43, 41, 32, 123, 10, 32, 32, 32, 32, 118, 97, 114, 32, 105, 116, 114, 32, 61, 32, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 91, 105, 93, 59, 10, 32, 32, 32, 32, 118, 97, 114, 32, 105, 102, 97, 99, 101, 73, 115, 32, 61, 32, 40, 118, 97, 108, 117, 101, 46, 105, 110, 116, 101, 114, 102, 97, 99, 101, 78, 97, 109, 101, 46, 116, 111, 76, 111, 119, 101, 114, 67, 97, 115, 101, 40, 41, 32, 61, 61, 61, 32, 105, 116, 114, 46, 110, 97, 109, 101, 46, 116, 111, 76, 111, 119, 101, 114, 67, 97, 115, 101, 40, 41, 41, 59, 10, 32, 32, 32, 32, 105, 102, 32, 40, 105, 102, 97, 99, 101, 73, 115, 32, 61, 61, 61, 32, 116, 114, 117, 101, 32, 38, 38, 32, 118, 97, 108, 117, 101, 46, 122, 111, 110, 101, 46, 101, 113, 117, 97, 108, 115, 40, 105, 116, 114, 46, 122, 111, 110, 101, 41, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 105, 116, 114, 46, 99, 97, 108, 108, 98, 97, 99, 107, 40, 118, 97, 108, 117, 101, 41, 59, 10, 32, 32, 32, 32, 125, 10, 32, 32, 125, 10, 125, 10, 47, 47, 47, 32, 82, 117, 110, 110, 105, 110, 103, 115, 116, 97, 116, 117, 115, 32, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 58, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 118, 101, 104, 105, 99, 108, 101, 83, 112, 101, 101, 100, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 101, 110, 103, 105, 110, 101, 83, 112, 101, 101, 100, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 112, 111, 119, 101, 114, 116, 114, 97, 105, 110, 84, 111, 114, 113, 117, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 97, 99, 99, 101, 108, 101, 114, 97, 116, 111, 114, 80, 101, 100, 97, 108, 80, 111, 115, 105, 116, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 116, 104, 114, 111, 116, 116, 108, 101, 80, 111, 115, 105, 116, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 116, 114, 97, 110, 115, 109, 105, 115, 115, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 99, 114, 117, 105, 115, 101, 67, 111, 110, 116, 114, 111, 108, 83, 116, 97, 116, 117, 115, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 108, 105, 103, 104, 116, 83, 116, 97, 116, 117, 115, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 104, 111, 114, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 99, 104, 105, 109, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 102, 117, 101, 108, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 101, 110, 103, 105, 110, 101, 79, 105, 108, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 97, 99, 99, 101, 108, 101, 114, 97, 116, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 101, 110, 103, 105, 110, 101, 67, 111, 111, 108, 97, 110, 116, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 115, 116, 101, 101, 114, 105, 110, 103, 87, 104, 101, 101, 108, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 119, 104, 101, 101, 108, 84, 105, 99, 107, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 105, 103, 110, 105, 116, 105, 111, 110, 84, 105, 109, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 121, 97, 119, 82, 97, 116, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 98, 114, 97, 107, 101, 79, 112, 101, 114, 97, 116, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 98, 117, 116, 116, 111, 110, 69, 118, 101, 110, 116, 39, 41, 59, 10, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 110, 105, 103, 104, 116, 77, 111, 100, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 100, 114, 105, 118, 105, 110, 103, 77, 111, 100, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 98, 114, 97, 107, 101, 79, 112, 101, 114, 97, 116, 105, 111, 110, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 116, 105, 114, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 100, 111, 111, 114, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 100, 101, 102, 114, 111, 115, 116, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 99, 108, 105, 109, 97, 116, 101, 67, 111, 110, 116, 114, 111, 108, 39, 41, 59, 10, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 98, 97, 116, 116, 101, 114, 121, 83, 116, 97, 116, 117, 115, 39, 41, 59, 10, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 116, 101, 109, 112, 101, 114, 97, 116, 117, 114, 101, 39, 41, 59, 10, 95, 100, 101, 102, 105, 110, 101, 86, 101, 104, 105, 99, 108, 101, 83, 105, 103, 110, 97, 108, 80, 114, 111, 112, 101, 114, 116, 121, 40, 101, 120, 112, 111, 114, 116, 115, 44, 32, 39, 111, 100, 111, 109, 101, 116, 101, 114, 39, 41, 59, 10, 10, 10, 0 };
diff --git a/xwalk/vehicle_api.js b/xwalk/vehicle_api.js
new file mode 100644
index 00000000..aeb721bf
--- /dev/null
+++ b/xwalk/vehicle_api.js
@@ -0,0 +1,264 @@
+// Copyright (c) 2014 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.
+
+var next_async_call_id = 0;
+var async_calls = {};
+
+var subscriptions = [];
+
+function vehicleInterfaceCommonContructor(obj, attname) {
+ obj.attributeName = attname;
+
+ var msg = {};
+ msg['method'] = 'zones';
+ msg['name'] = obj.attributeName;
+
+ obj._zones = new Zone;
+
+ var call = new AsyncCall(function(data) {
+ obj._zones = data;
+ });
+
+ async_calls[next_async_call_id] = call;
+ msg.asyncCallId = next_async_call_id;
+ ++next_async_call_id;
+
+ extension.postMessage(JSON.stringify(msg));
+
+ Object.defineProperty(obj, 'zones', { get: function() { return obj._zones } });
+}
+
+function VehicleInterface(attname) {
+ vehicleInterfaceCommonContructor(this, attname);
+}
+
+VehicleInterface.prototype.get = function(zone) {
+ var msg = {};
+ msg['method'] = 'get';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+
+ return createPromise(msg);
+};
+
+function VehicleSignalInterface(attname) {
+ vehicleInterfaceCommonContructor(this, attname);
+}
+
+VehicleSignalInterface.prototype = VehicleInterface.prototype;
+
+VehicleSignalInterface.prototype.subscribe = function(callback, zone) {
+ if (!zone) zone = new Zone();
+
+ var msg = {};
+ msg['method'] = 'subscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+
+ extension.postMessage(JSON.stringify(msg));
+
+ msg['callback'] = callback;
+
+ subscriptions.push(msg);
+
+ return subscriptions.length - 1;
+};
+
+VehicleSignalInterface.prototype.unsubscribe = function(handle) {
+ var obj = subscriptions[handle];
+ subscriptions.splice(handle, 1);
+
+ var unsubscribe = true;
+
+ for (var i = 0; i < subscriptions.length; i++) {
+ var testObj = subscriptions[i];
+
+ if (testObj.name === obj.name && testObj.zone.equals(obj.zone)) {
+ unsubscribe = false;
+ break;
+ }
+ }
+
+ if (unsubscribe) {
+ var msg = {};
+ msg['method'] = 'unsubscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = obj.zone;
+
+ extension.postMessage(JSON.stringify(msg));
+ }
+};
+
+VehicleSignalInterface.prototype.set = function (value, zone) {
+ var msg = {};
+ msg['method'] = 'set';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+ msg['value'] = value;
+
+ return createPromise(msg);
+}
+
+function AsyncCall(resolve, reject) {
+ this.resolve = resolve;
+ this.reject = reject;
+}
+
+function createPromise(msg) {
+ var promise = new Promise(function(resolve, reject) {
+ async_calls[next_async_call_id] = new AsyncCall(resolve, reject);
+ });
+
+ msg.asyncCallId = next_async_call_id;
+ extension.postMessage(JSON.stringify(msg));
+ ++next_async_call_id;
+ return promise;
+}
+
+window.Zone = function(zone) {
+ this.value = zone ? zone : [];
+
+ Object.defineProperty(this, 'driver',
+ { enumerable: false, get: function() {
+ return new Zone(['Front', 'Left']);
+ } });
+};
+
+window.Zone.prototype.equals = function(zone) {
+ var is_equal = true;
+
+ for (var i = 0; i < zone.value.length; i++) {
+ is_equal &= this.value.indexOf(zone.value[i]) !== -1;
+ }
+
+ for (var i = 0; i < this.value.length; i++) {
+ is_equal &= zone.value.indexOf(this.value[i]) !== -1;
+ }
+
+ return is_equal;
+};
+
+function _defineVehicleProperty(obj, prop) {
+ Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleInterface(prop) });
+}
+
+function _defineVehicleSignalProperty(obj, prop) {
+ Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleSignalInterface(prop) });
+}
+
+extension.setMessageListener(function(json) {
+ try {
+ var msg = JSON.parse(json);
+
+ switch (msg.method) {
+ case 'get':
+ handlePromiseReply(msg);
+ break;
+ case 'zones':
+ handleZonesReply(msg);
+ break;
+ case 'subscribe':
+ handleSubscribeReply(msg);
+ break;
+ case 'set':
+ handlePromiseReply(msg);
+ break;
+ default:
+ break;
+ }
+ } catch (error) {
+ console.log('Error in message listener: ' + error);
+ }
+});
+
+function handlePromiseReply(msg) {
+ var cbobj = async_calls[msg.asyncCallId];
+
+ if (msg.error) {
+ var error = {};
+ error.error = msg.value;
+ switch (msg.value) {
+ case 'permission_denied':
+ error.message = 'Permission denied';
+ break;
+ case 'invalid_operation':
+ error.message = 'Invalid operation';
+ break;
+ case 'timeout':
+ error.message = 'Operation timed out';
+ break;
+ case 'invalid_zone':
+ error.message = 'Zone invalid or not found';
+ break;
+ case 'unknown':
+ error.message = 'An unknown error occured';
+ break;
+ default:
+ break;
+ }
+
+ cbobj.reject(error);
+ } else {
+ cbobj.resolve(msg.value);
+ }
+
+ delete async_calls[msg.asyncCallId];
+}
+
+function handleZonesReply(msg) {
+ var cbobj = async_calls[msg.asyncCallId];
+
+ if (cbobj)
+ cbobj.resolve(new Zone(msg.value));
+}
+
+function handleSubscribeReply(msg) {
+ delete async_calls[msg.asyncCallId];
+ var value = msg.value;
+ value.zone = new Zone(value.zone);
+
+ for (var i = 0; i < subscriptions.length; i++) {
+ var itr = subscriptions[i];
+ var ifaceIs = (value.interfaceName.toLowerCase() === itr.name.toLowerCase());
+ if (ifaceIs === true && value.zone.equals(itr.zone)) {
+ itr.callback(value);
+ }
+ }
+}
+/// Runningstatus attributes:
+_defineVehicleSignalProperty(exports, 'vehicleSpeed');
+_defineVehicleSignalProperty(exports, 'engineSpeed');
+_defineVehicleSignalProperty(exports, 'powertrainTorque');
+_defineVehicleSignalProperty(exports, 'acceleratorPedalPosition');
+_defineVehicleSignalProperty(exports, 'throttlePosition');
+_defineVehicleSignalProperty(exports, 'transmission');
+_defineVehicleSignalProperty(exports, 'cruiseControlStatus');
+_defineVehicleSignalProperty(exports, 'lightStatus');
+_defineVehicleSignalProperty(exports, 'horn');
+_defineVehicleSignalProperty(exports, 'chime');
+_defineVehicleSignalProperty(exports, 'fuel');
+_defineVehicleSignalProperty(exports, 'engineOil');
+_defineVehicleSignalProperty(exports, 'acceleration');
+_defineVehicleSignalProperty(exports, 'engineCoolant');
+_defineVehicleSignalProperty(exports, 'steeringWheel');
+_defineVehicleSignalProperty(exports, 'wheelTick');
+_defineVehicleSignalProperty(exports, 'ignitionTime');
+_defineVehicleSignalProperty(exports, 'yawRate');
+_defineVehicleSignalProperty(exports, 'brakeOperation');
+_defineVehicleSignalProperty(exports, 'buttonEvent');
+
+_defineVehicleSignalProperty(exports, 'nightMode');
+_defineVehicleSignalProperty(exports, 'drivingMode');
+_defineVehicleSignalProperty(exports, 'brakeOperation');
+_defineVehicleSignalProperty(exports, 'tire');
+_defineVehicleSignalProperty(exports, 'door');
+_defineVehicleSignalProperty(exports, 'defrost');
+_defineVehicleSignalProperty(exports, 'climateControl');
+
+_defineVehicleSignalProperty(exports, 'batteryStatus');
+
+_defineVehicleSignalProperty(exports, 'temperature');
+_defineVehicleSignalProperty(exports, 'odometer');
+
+
diff --git a/xwalk/vehicle_extension.cc b/xwalk/vehicle_extension.cc
new file mode 100644
index 00000000..a021c142
--- /dev/null
+++ b/xwalk/vehicle_extension.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2014 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.
+
+#include "vehicle_extension.h"
+
+#include "vehicle_instance.h"
+
+common::Extension* CreateExtension() {
+ return new VehicleExtension();
+}
+
+extern const char kSource_vehicle_api[];
+
+VehicleExtension::VehicleExtension() {
+ SetExtensionName("navigator.vehicle");
+ SetJavaScriptAPI(kSource_vehicle_api);
+
+ const char* entry_points[] = {"Zone", NULL};
+
+ SetExtraJSEntryPoints(entry_points);
+}
+
+VehicleExtension::~VehicleExtension() {
+}
+
+common::Instance* VehicleExtension::CreateInstance() {
+ return new VehicleInstance;
+}
diff --git a/xwalk/vehicle_extension.h b/xwalk/vehicle_extension.h
new file mode 100644
index 00000000..ebd50811
--- /dev/null
+++ b/xwalk/vehicle_extension.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2014 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.
+
+#ifndef VEHICLE_VEHICLE_EXTENSION_H_
+#define VEHICLE_VEHICLE_EXTENSION_H_
+
+#include "common/extension.h"
+
+class VehicleExtension : public common::Extension {
+ public:
+ VehicleExtension();
+ virtual ~VehicleExtension();
+
+ private:
+ // common::Extension implementation.
+ virtual common::Instance* CreateInstance();
+};
+
+#endif // VEHICLE_VEHICLE_EXTENSION_H_
diff --git a/xwalk/vehicle_instance.cc b/xwalk/vehicle_instance.cc
new file mode 100644
index 00000000..9a8091d8
--- /dev/null
+++ b/xwalk/vehicle_instance.cc
@@ -0,0 +1,134 @@
+// Copyright (c) 2014 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.
+
+#include "vehicle_instance.h"
+
+#include <abstractpropertytype.h>
+
+#include <algorithm>
+#include <string>
+
+#include "vehicle.h"
+
+VehicleInstance::VehicleInstance(): vehicle_(new Vehicle(this)) {
+ DebugOut::setDebugThreshhold(5);
+}
+
+void VehicleInstance::HandleMessage(const char* message) {
+ DebugOut() << "VehicleInstance message received " << message << endl;
+
+ picojson::value v;
+
+ std::string err;
+ picojson::parse(v, message, message + strlen(message), &err);
+ if (!err.empty()) {
+ return;
+ }
+
+ std::string method = v.get("method").to_str();
+
+ Zone::Type amb_zone = 0;
+ if (v.contains("zone")) {
+ picojson::value zone = v.get("zone");
+ if (zone.is<picojson::object>() && zone.contains("value")) {
+ picojson::array zones = zone.get("value").get<picojson::array>();
+ amb_zone = ZoneToAMBZone(zones);
+ } else {
+ int callback_id = -1;
+ if (v.contains("asyncCallId"))
+ callback_id = v.get("asyncCallId").get<double>();
+ PostError(callback_id, method, "invalid_zone");
+ return;
+ }
+ }
+
+ if (method == "get") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+ Zone::Type amb_zone = 0;
+
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Get(attribute, amb_zone, callback_id);
+ } else if (method == "zones") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->GetZones(attribute, callback_id);
+ } else if (method == "subscribe") {
+ std::string attribute = v.get("name").to_str();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Subscribe(attribute, amb_zone);
+ } else if (method == "unsubscribe") {
+ std::string attribute = v.get("name").to_str();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Unsubscribe(attribute, amb_zone);
+ } else if (method == "set") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+ Zone::Type amb_zone = 0;
+
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ if (!v.get("value").is<picojson::object>()) {
+ PostError(callback_id, "set", "invalid_operation");
+ }
+ picojson::object value = v.get("value").get<picojson::object>();
+
+ vehicle_->Set(attribute, value, amb_zone, callback_id);
+ }
+}
+
+void VehicleInstance::HandleSyncMessage(const char* message) {
+}
+
+int VehicleInstance::ZoneToAMBZone(picojson::array zones) {
+ Zone::Type amb_zone = 0;
+
+ for (auto zone : zones) {
+ std::string tempzone = zone.to_str();
+
+ if (tempzone == "Front") {
+ amb_zone |= Zone::Front;
+ } else if (tempzone == "Middle") {
+ amb_zone |= Zone::Middle;
+ } else if (tempzone == "Right") {
+ amb_zone |= Zone::Right;
+ } else if (tempzone == "Left") {
+ amb_zone |= Zone::Left;
+ } else if (tempzone == "Rear") {
+ amb_zone |= Zone::Rear;
+ } else if (tempzone == "Center") {
+ amb_zone |= Zone::Center;
+ }
+ }
+
+ return amb_zone;
+}
+
+void VehicleInstance::PostError(double callback_id, const std::string& method,
+ const std::string& error) {
+ picojson::object msg;
+ msg["method"] = picojson::value(method);
+ msg["error"] = picojson::value(true);
+ msg["value"] = picojson::value(error);
+ if (callback_id != -1) {
+ msg["asyncCallId"] =
+ picojson::value(static_cast<double>(callback_id));
+ }
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Error Reply message: " << message << endl;
+
+ PostMessage(message.c_str());
+}
diff --git a/xwalk/vehicle_instance.h b/xwalk/vehicle_instance.h
new file mode 100644
index 00000000..33dc8ba8
--- /dev/null
+++ b/xwalk/vehicle_instance.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2014 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.
+
+#ifndef VEHICLE_VEHICLE_INSTANCE_H_
+#define VEHICLE_VEHICLE_INSTANCE_H_
+
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "vehicle.h"
+
+class VehicleInstance : public common::Instance {
+ public:
+ VehicleInstance();
+ virtual ~VehicleInstance() {}
+
+ private:
+ // common::Instance implementation.
+ virtual void HandleMessage(const char* msg);
+ virtual void HandleSyncMessage(const char* msg);
+
+ int ZoneToAMBZone(picojson::array);
+
+ void PostError(double callback_id, const std::string& method,
+ const std::string& error);
+
+ Vehicle* vehicle_;
+};
+
+#endif // VEHICLE_VEHICLE_INSTANCE_H_