# Targets names
SET(TARGET_RUNTIME "wrt")
SET(TARGET_COMMON_STATIC "wrt-common-static")
-SET(TARGET_EXTENSION "wrt-extension")
+SET(TARGET_EXTENSION_STATIC "wrt-extension-static")
SET(TARGET_INJECTED_BUNDLE "wrt-injected-bundle")
# Sub Directories
files=`find $1 -name "*.c" -or -name "*.cc" -or -name "*.h"`
+exclude_files="picojson.h"
+
ret=0
for x in $files; do
+ if [[ $exclude_files =~ $(basename $x) ]]; then
+ continue
+ fi
+
$(dirname $0)/cpplint.py \
--filter=-build/header_guard \
$x
%files
%attr(755,root,root) %{_bindir}/wrt
%attr(644,root,root) %{_datadir}/edje/wrt/wrt.edj
+%attr(644,root,root) %{_libdir}/libwrt-injected-bundle.so
SET(BASE_SRCDIR ${PROJECT_SOURCE_DIR}/src)
ADD_SUBDIRECTORY(common)
+ADD_SUBDIRECTORY(extension)
+ADD_SUBDIRECTORY(bundle)
ADD_SUBDIRECTORY(runtime)
--- /dev/null
+# Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Dependencies
+PKG_CHECK_MODULES(TARGET_INJECTED_BUNDLE_DEPS REQUIRED
+ elementary
+ chromium-efl
+)
+
+# Include Directories
+SET(TARGET_INJECTED_BUNDLE_INCS
+ ${BASE_SRCDIR}
+ ${TARGET_INJECTED_BUNDLE_DEPS_INCLUDE_DIRS}
+)
+
+# Libraries
+SET(TARGET_INJECTED_BUNDLE_LIBS
+ ${TARGET_INJECTED_BUNDLE_DEPS_LIBRARIES}
+)
+
+# Source Files
+SET(TARGET_INJECTED_BUNDLE_SRCS
+ ${BASE_SRCDIR}/bundle/injected_bundle.cc
+)
+
+INCLUDE_DIRECTORIES(${TARGET_INJECTED_BUNDLE_INCS})
+ADD_LIBRARY(${TARGET_INJECTED_BUNDLE} SHARED
+ ${TARGET_INJECTED_BUNDLE_SRCS}
+)
+TARGET_LINK_LIBRARIES(${TARGET_INJECTED_BUNDLE}
+ ${TARGET_INJECTED_BUNDLE_LIBS}
+ ${TARGET_COMMON_STATIC}
+ "-ldl"
+)
+
+SET_TARGET_PROPERTIES(${TARGET_INJECTED_BUNDLE} PROPERTIES
+ COMPILE_FLAGS -fPIC)
+SET_TARGET_PROPERTIES(${TARGET_INJECTED_BUNDLE} PROPERTIES
+ LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both"
+ OUTPUT_NAME ${TARGET_INJECTED_BUNDLE}
+)
+
+INSTALL(TARGETS ${TARGET_INJECTED_BUNDLE}
+ DESTINATION lib/
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)
+
+
// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
+#include <v8.h>
+#include <ewk_ipc_message.h>
+#include <string>
+
+extern "C" void DynamicSetWidgetInfo(int widget_id) {
+}
+
+extern "C" void DynamicPluginStartSession(int widget_id,
+ v8::Handle<v8::Context> context,
+ int routing_handle,
+ double scale,
+ const char* encoded_bundle,
+ const char* theme,
+ const char* base_url) {
+}
+
+extern "C" void DynamicPluginStopSession(
+ int widget_id, v8::Handle<v8::Context> context) {
+}
+
+extern "C" void DynamicUrlParsing(
+ std::string* old_url, std::string* new_url, int widget_id) {
+}
+
+extern "C" void DynamicDatabaseAttach(int attach) {
+}
+
+extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& data) {
+}
+
+extern "C" void DynamicPreloading() {
+}
)
SET(TARGET_COMMON_STATIC_SRCS
- ${PROJECT_SOURCE_DIR}/src/common/file_utils.cc
+ ${BASE_SRCDIR}/common/file_utils.cc
+ ${BASE_SRCDIR}/common/message_types.cc
)
INCLUDE_DIRECTORIES(${TARGET_COMMON_STATIC_INCS})
namespace wrt {
namespace utils {
-bool Exist(const std::string& path) {
+bool Exists(const std::string& path) {
return (access(path.c_str(), F_OK) != -1);
}
namespace wrt {
namespace utils {
-bool Exist(const std::string& path);
+bool Exists(const std::string& path);
std::string BaseName(const std::string& path);
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/message_types.h"
+
+namespace wrt {
+
+namespace message_types {
+
+const char* kExtensionTypePrefix = "tizen://extension/";
+const char* kExtensionEPCreated = "tizen://extension/ep_created";
+const char* kExtensionGetExtensions = "tizen://extension/get_extensions";
+const char* kExtensionCreateInstance = "tizen://extension/create_instance";
+const char* kExtensionDestroyInstance = "tizen://extension/destroy_instance";
+const char* kExtensionCallSync = "tizen://extension/call_sync";
+const char* kExtensionCallAsync = "tizen://extension/call_async";
+const char* kExtensionPostMessageToJS = "tizen://extension/post_message_to_js";
+
+} // namespace message_types
+
+} // namespace wrt
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_COMMON_MESSAGE_TYPES_H_
+#define WRT_COMMON_MESSAGE_TYPES_H_
+
+namespace wrt {
+
+namespace message_types {
+
+extern const char* kExtensionTypePrefix;
+extern const char* kExtensionEPCreated;
+extern const char* kExtensionGetExtensions;
+extern const char* kExtensionCreateInstance;
+extern const char* kExtensionDestroyInstance;
+extern const char* kExtensionCallSync;
+extern const char* kExtensionCallAsync;
+extern const char* kExtensionPostMessageToJS;
+
+} // namespace message_types
+
+} // namespace wrt
+
+#endif // WRT_COMMON_MESSAGE_TYPES_H_
--- /dev/null
+/*
+ * Copyright 2009-2010 Cybozu Labs, Inc.
+ * Copyright 2011-2014 Kazuho Oku
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef picojson_h
+#define picojson_h
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+// for isnan/isinf
+#if __cplusplus>=201103L
+# include <cmath>
+#else
+extern "C" {
+# ifdef _MSC_VER
+# include <float.h>
+# elif defined(__INTEL_COMPILER)
+# include <mathimf.h>
+# else
+# include <math.h>
+# endif
+}
+#endif
+
+// experimental support for int64_t (see README.mkdn for detail)
+#ifdef PICOJSON_USE_INT64
+# define __STDC_FORMAT_MACROS
+# include <errno.h>
+# include <inttypes.h>
+#endif
+
+// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
+#ifndef PICOJSON_USE_LOCALE
+# define PICOJSON_USE_LOCALE 1
+#endif
+#if PICOJSON_USE_LOCALE
+extern "C" {
+# include <locale.h>
+}
+#endif
+
+#ifndef PICOJSON_ASSERT
+# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0)
+#endif
+
+#ifdef _MSC_VER
+ #define SNPRINTF _snprintf_s
+ #pragma warning(push)
+ #pragma warning(disable : 4244) // conversion from int to char
+ #pragma warning(disable : 4127) // conditional expression is constant
+ #pragma warning(disable : 4702) // unreachable code
+#else
+ #define SNPRINTF snprintf
+#endif
+
+namespace picojson {
+
+ enum {
+ null_type,
+ boolean_type,
+ number_type,
+ string_type,
+ array_type,
+ object_type
+#ifdef PICOJSON_USE_INT64
+ , int64_type
+#endif
+ };
+
+ enum {
+ INDENT_WIDTH = 2
+ };
+
+ struct null {};
+
+ class value {
+ public:
+ typedef std::vector<value> array;
+ typedef std::map<std::string, value> object;
+ union _storage {
+ bool boolean_;
+ double number_;
+#ifdef PICOJSON_USE_INT64
+ int64_t int64_;
+#endif
+ std::string* string_;
+ array* array_;
+ object* object_;
+ };
+ protected:
+ int type_;
+ _storage u_;
+ public:
+ value();
+ value(int type, bool);
+ explicit value(bool b);
+#ifdef PICOJSON_USE_INT64
+ explicit value(int64_t i);
+#endif
+ 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;
+ value& get(size_t idx);
+ value& get(const std::string& key);
+
+ 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, bool prettify = false) const;
+ std::string serialize(bool prettify = false) const;
+ private:
+ template <typename T> value(const T*); // intentionally defined to block implicit conversion of pointer to bool
+ template <typename Iter> static void _indent(Iter os, int indent);
+ template <typename Iter> void _serialize(Iter os, int indent) const;
+ std::string _serialize(int indent) const;
+ };
+
+ 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);
+#ifdef PICOJSON_USE_INT64
+ INIT(int64_, 0);
+#endif
+ 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;
+ }
+
+#ifdef PICOJSON_USE_INT64
+ inline value::value(int64_t i) : type_(int64_type) {
+ u_.int64_ = i;
+ }
+#endif
+
+ inline value::value(double n) : type_(number_type) {
+ if (
+#ifdef _MSC_VER
+ ! _finite(n)
+#elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf))
+ std::isnan(n) || std::isinf(n)
+#else
+ isnan(n) || isinf(n)
+#endif
+ ) {
+ throw std::overflow_error("");
+ }
+ 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) {
+ value t(x);
+ swap(t);
+ }
+ 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)
+#ifdef PICOJSON_USE_INT64
+ IS(int64_t, int64)
+#endif
+ IS(std::string, string)
+ IS(array, array)
+ IS(object, object)
+#undef IS
+ template <> inline bool value::is<double>() const {
+ return type_ == number_type
+#ifdef PICOJSON_USE_INT64
+ || type_ == int64_type
+#endif
+ ;
+ }
+
+#define GET(ctype, var) \
+ template <> inline const ctype& value::get<ctype>() const { \
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
+ && is<ctype>()); \
+ return var; \
+ } \
+ template <> inline ctype& value::get<ctype>() { \
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
+ && is<ctype>()); \
+ return var; \
+ }
+ GET(bool, u_.boolean_)
+ GET(std::string, *u_.string_)
+ GET(array, *u_.array_)
+ GET(object, *u_.object_)
+#ifdef PICOJSON_USE_INT64
+ GET(double, (type_ == int64_type && (const_cast<value*>(this)->type_ = number_type, const_cast<value*>(this)->u_.number_ = u_.int64_), u_.number_))
+ GET(int64_t, u_.int64_)
+#else
+ GET(double, u_.number_)
+#endif
+#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;
+ PICOJSON_ASSERT(is<array>());
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
+ }
+
+ inline value& value::get(size_t idx) {
+ static value s_null;
+ PICOJSON_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;
+ PICOJSON_ASSERT(is<object>());
+ object::const_iterator i = u_.object_->find(key);
+ return i != u_.object_->end() ? i->second : s_null;
+ }
+
+ inline value& value::get(const std::string& key) {
+ static value s_null;
+ PICOJSON_ASSERT(is<object>());
+ object::iterator i = u_.object_->find(key);
+ return i != u_.object_->end() ? i->second : s_null;
+ }
+
+ inline bool value::contains(size_t idx) const {
+ PICOJSON_ASSERT(is<array>());
+ return idx < u_.array_->size();
+ }
+
+ inline bool value::contains(const std::string& key) const {
+ PICOJSON_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";
+#ifdef PICOJSON_USE_INT64
+ case int64_type: {
+ char buf[sizeof("-9223372036854775808")];
+ SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
+ return buf;
+ }
+#endif
+ 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_);
+#if PICOJSON_USE_LOCALE
+ char *decimal_point = localeconv()->decimal_point;
+ if (strcmp(decimal_point, ".") != 0) {
+ size_t decimal_point_len = strlen(decimal_point);
+ for (char *p = buf; *p != '\0'; ++p) {
+ if (strncmp(p, decimal_point, decimal_point_len) == 0) {
+ return std::string(buf, p) + "." + (p + decimal_point_len);
+ }
+ }
+ }
+#endif
+ return buf;
+ }
+ case string_type: return *u_.string_;
+ case array_type: return "array";
+ case object_type: return "object";
+ default: PICOJSON_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 (static_cast<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, bool prettify) const {
+ return _serialize(oi, prettify ? 0 : -1);
+ }
+
+ inline std::string value::serialize(bool prettify) const {
+ return _serialize(prettify ? 0 : -1);
+ }
+
+ template <typename Iter> void value::_indent(Iter oi, int indent) {
+ *oi++ = '\n';
+ for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
+ *oi++ = ' ';
+ }
+ }
+
+ template <typename Iter> void value::_serialize(Iter oi, int indent) const {
+ switch (type_) {
+ case string_type:
+ serialize_str(*u_.string_, oi);
+ break;
+ case array_type: {
+ *oi++ = '[';
+ if (indent != -1) {
+ ++indent;
+ }
+ for (array::const_iterator i = u_.array_->begin();
+ i != u_.array_->end();
+ ++i) {
+ if (i != u_.array_->begin()) {
+ *oi++ = ',';
+ }
+ if (indent != -1) {
+ _indent(oi, indent);
+ }
+ i->_serialize(oi, indent);
+ }
+ if (indent != -1) {
+ --indent;
+ if (! u_.array_->empty()) {
+ _indent(oi, indent);
+ }
+ }
+ *oi++ = ']';
+ break;
+ }
+ case object_type: {
+ *oi++ = '{';
+ if (indent != -1) {
+ ++indent;
+ }
+ for (object::const_iterator i = u_.object_->begin();
+ i != u_.object_->end();
+ ++i) {
+ if (i != u_.object_->begin()) {
+ *oi++ = ',';
+ }
+ if (indent != -1) {
+ _indent(oi, indent);
+ }
+ serialize_str(i->first, oi);
+ *oi++ = ':';
+ if (indent != -1) {
+ *oi++ = ' ';
+ }
+ i->second._serialize(oi, indent);
+ }
+ if (indent != -1) {
+ --indent;
+ if (! u_.object_->empty()) {
+ _indent(oi, indent);
+ }
+ }
+ *oi++ = '}';
+ break;
+ }
+ default:
+ copy(to_str(), oi);
+ break;
+ }
+ if (indent == 0) {
+ *oi++ = '\n';
+ }
+ }
+
+ inline std::string value::_serialize(int indent) const {
+ std::string s;
+ _serialize(std::back_inserter(s), indent);
+ 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;
+ ++cur_;
+ return last_ch_;
+ }
+ void ungetc() {
+ if (last_ch_ != -1) {
+ PICOJSON_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;
+ }
+ size_t idx = 0;
+ if (in.expect(']')) {
+ return ctx.parse_array_stop(idx);
+ }
+ do {
+ if (! ctx.parse_array_item(in, idx)) {
+ return false;
+ }
+ idx++;
+ } while (in.expect(','));
+ return in.expect(']') && ctx.parse_array_stop(idx);
+ }
+
+ 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 std::string _parse_number(input<Iter>& in) {
+ std::string num_str;
+ while (1) {
+ int ch = in.getc();
+ if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-'
+ || ch == 'e' || ch == 'E') {
+ num_str.push_back(ch);
+ } else if (ch == '.') {
+#if PICOJSON_USE_LOCALE
+ num_str += localeconv()->decimal_point;
+#else
+ num_str.push_back('.');
+#endif
+ } else {
+ in.ungetc();
+ break;
+ }
+ }
+ return num_str;
+ }
+
+ 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 == '-') {
+ double f;
+ char *endp;
+ in.ungetc();
+ std::string num_str = _parse_number(in);
+ if (num_str.empty()) {
+ return false;
+ }
+#ifdef PICOJSON_USE_INT64
+ {
+ errno = 0;
+ intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
+ if (errno == 0
+ && std::numeric_limits<int64_t>::min() <= ival
+ && ival <= std::numeric_limits<int64_t>::max()
+ && endp == num_str.c_str() + num_str.size()) {
+ ctx.set_int64(ival);
+ return true;
+ }
+ }
+#endif
+ f = strtod(num_str.c_str(), &endp);
+ if (endp == num_str.c_str() + num_str.size()) {
+ ctx.set_number(f);
+ return true;
+ }
+ return false;
+ }
+ break;
+ }
+ in.ungetc();
+ return false;
+ }
+
+ class deny_parse_context {
+ public:
+ bool set_null() { return false; }
+ bool set_bool(bool) { return false; }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t) { return false; }
+#endif
+ 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_array_stop(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;
+ }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t i) {
+ *out_ = value(i);
+ return true;
+ }
+#endif
+ 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_array_stop(size_t) { return true; }
+ 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; }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t) { return true; }
+#endif
+ 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_array_stop(size_t) { return true; }
+ 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, const std::string& s) {
+ std::string err;
+ parse(out, s.begin(), s.end(), &err);
+ return 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
+ PICOJSON_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
+# Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+PKG_CHECK_MODULES(TARGET_EXTENSION_STATIC_DEPS
+ dlog
+ elementary
+ chromium-efl
+ REQUIRED
+)
+
+SET(TARGET_EXTENSION_STATIC_INCS
+ ${BASE_SRCDIR}
+ ${TARGET_EXTENSION_STATIC_DEPS_INCLUDE_DIRS}
+)
+
+SET(TARGET_EXTENSION_STATIC_SRCS
+ ${BASE_SRCDIR}/extension/extension.cc
+ ${BASE_SRCDIR}/extension/extension_instance.cc
+ ${BASE_SRCDIR}/extension/extension_adapter.cc
+ ${BASE_SRCDIR}/extension/extension_server.cc
+)
+
+INCLUDE_DIRECTORIES(${TARGET_EXTENSION_STATIC_INCS})
+ADD_LIBRARY(${TARGET_EXTENSION_STATIC} STATIC
+ ${TARGET_EXTENSION_STATIC_SRCS}
+)
#include "extension/extension.h"
+#include <dlfcn.h>
+#include <string>
+
+#include "common/logger.h"
+#include "extension/extension_adapter.h"
+#include "extension/xwalk/XW_Extension.h"
+
namespace wrt {
-Extension::Extension() {
+Extension::Extension(const std::string& path, ExtensionDelegate* delegate)
+ : initialized_(false),
+ library_path_(path),
+ xw_extension_(0),
+ use_trampoline_(true),
+ delegate_(delegate),
+ created_instance_callback_(NULL),
+ destroyed_instance_callback_(NULL),
+ shutdown_callback_(NULL),
+ handle_msg_callback_(NULL),
+ handle_sync_msg_callback_(NULL) {
}
Extension::~Extension() {
+ if (!initialized_)
+ return;
+
+ if (shutdown_callback_)
+ shutdown_callback_(xw_extension_);
+ ExtensionAdapter::GetInstance()->UnregisterExtension(this);
+}
+
+bool Extension::Initialize() {
+ if (initialized_)
+ return true;
+
+ void* handle = dlopen(library_path_.c_str(), RTLD_LAZY);
+ if (!handle) {
+ LoggerE("Error loading extension '%s' : %s",
+ library_path_.c_str(), dlerror());
+ return false;
+ }
+
+ XW_Initialize_Func initialize = reinterpret_cast<XW_Initialize_Func>(
+ dlsym(handle, "XW_Initialize"));
+ if (!initialize) {
+ LoggerE(
+ "Error loading extension '%s' : couldn't get XW_Initialize function",
+ library_path_.c_str());
+ dlclose(handle);
+ return false;
+ }
+
+ ExtensionAdapter* adapter = ExtensionAdapter::GetInstance();
+ xw_extension_ = adapter->GetNextXWExtension();
+ adapter->RegisterExtension(this);
+
+ int ret = initialize(xw_extension_, ExtensionAdapter::GetInterface);
+ if (ret != XW_OK) {
+ LoggerE(
+ "Error loading extension '%s' : XW_Initialize() returned error value.",
+ library_path_.c_str());
+ dlclose(handle);
+ return false;
+ }
+
+ initialized_ = true;
+ return true;
+}
+
+ExtensionInstance* Extension::CreateInstance() {
+ ExtensionAdapter* adapter = ExtensionAdapter::GetInstance();
+ XW_Instance xw_instance = adapter->GetNextXWInstance();
+ return new ExtensionInstance(this, xw_instance);
}
+void Extension::GetRuntimeVariable(const char* key, char* value,
+ size_t value_len) {
+ if (delegate_) {
+ delegate_->GetRuntimeVariable(key, value, value_len);
+ }
+}
+int Extension::CheckAPIAccessControl(const char* /*api_name*/) {
+ // Not Supported
+ return XW_OK;
+}
+
+int Extension::RegisterPermissions(const char* /*perm_table*/) {
+ // Not Supported
+ return XW_OK;
+}
} // namespace wrt
#include <string>
#include <vector>
+#include "extension/extension_instance.h"
+#include "extension/xwalk/XW_Extension.h"
+#include "extension/xwalk/XW_Extension_SyncMessage.h"
+
namespace wrt {
+class ExtensionAdapter;
+class ExtensionInstance;
+
class Extension {
public:
- Extension();
+ typedef std::vector<std::string> StringVector;
+
+ class ExtensionDelegate {
+ public:
+ virtual void GetRuntimeVariable(const char* key, char* value,
+ size_t value_len) = 0;
+ };
+
+ Extension(const std::string& path, ExtensionDelegate* delegate);
virtual ~Extension();
+ bool Initialize();
+ ExtensionInstance* CreateInstance();
+
std::string name() const { return name_; }
+
std::string javascript_api() const { return javascript_api_; }
- const std::vector<std::string>& entry_points() { return entry_points_; }
- protected:
+ const StringVector& entry_points() const {
+ return entry_points_;
+ }
+
+ bool use_trampoline() const {
+ return use_trampoline_;
+ }
+
+ void set_name(const std::string& name) {
+ name_ = name;
+ }
+
+ void set_javascript_api(const std::string& javascript_api) {
+ javascript_api_ = javascript_api;
+ }
+
+ void set_use_trampoline(bool use_trampoline) {
+ use_trampoline_ = use_trampoline;
+ }
+
+ private:
+ friend class ExtensionAdapter;
+ friend class ExtensionInstance;
+
+ void GetRuntimeVariable(const char* key, char* value, size_t value_len);
+ int CheckAPIAccessControl(const char* api_name);
+ int RegisterPermissions(const char* perm_table);
+
+ bool initialized_;
+ std::string library_path_;
+ XW_Extension xw_extension_;
+
std::string name_;
std::string javascript_api_;
- std::vector<std::string> entry_points_;
+ StringVector entry_points_;
+ bool use_trampoline_;
- private:
+ ExtensionDelegate* delegate_;
+
+ XW_CreatedInstanceCallback created_instance_callback_;
+ XW_DestroyedInstanceCallback destroyed_instance_callback_;
+ XW_ShutdownCallback shutdown_callback_;
+ XW_HandleMessageCallback handle_msg_callback_;
+ XW_HandleSyncMessageCallback handle_sync_msg_callback_;
};
} // namespace wrt
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extension/extension_adapter.h"
+
+#include <string>
+
+#include "common/logger.h"
+
+namespace wrt {
+
+ExtensionAdapter::ExtensionAdapter()
+ : next_xw_extension_(1),
+ next_xw_instance_(1) {
+}
+
+ExtensionAdapter::~ExtensionAdapter() {
+}
+
+ExtensionAdapter* ExtensionAdapter::GetInstance() {
+ static ExtensionAdapter self;
+ return &self;
+}
+
+XW_Extension ExtensionAdapter::GetNextXWExtension() {
+ return next_xw_extension_++;
+}
+
+XW_Instance ExtensionAdapter::GetNextXWInstance() {
+ return next_xw_instance_++;
+}
+
+void ExtensionAdapter::RegisterExtension(Extension* extension) {
+ XW_Extension xw_extension = extension->xw_extension_;
+ if (!(xw_extension > 0 && xw_extension < next_xw_extension_)) {
+ LoggerW("xw_extension (%d) is invalid.", xw_extension);
+ return;
+ }
+ if (extension_map_.find(xw_extension) == extension_map_.end())
+ extension_map_[xw_extension] = extension;
+}
+
+void ExtensionAdapter::UnregisterExtension(Extension* extension) {
+ XW_Extension xw_extension = extension->xw_extension_;
+ if (!(xw_extension > 0 && xw_extension < next_xw_extension_)) {
+ LoggerW("xw_extension (%d) is invalid.", xw_extension);
+ return;
+ }
+ if (extension_map_.find(xw_extension) != extension_map_.end())
+ extension_map_.erase(xw_extension);
+}
+
+void ExtensionAdapter::RegisterInstance(ExtensionInstance* instance) {
+ XW_Instance xw_instance = instance->xw_instance_;
+ if (!(xw_instance > 0 && xw_instance < next_xw_instance_)) {
+ LoggerW("xw_instance (%d) is invalid.", xw_instance);
+ return;
+ }
+ if (instance_map_.find(xw_instance) == instance_map_.end())
+ instance_map_[xw_instance] = instance;
+}
+
+void ExtensionAdapter::UnregisterInstance(ExtensionInstance* instance) {
+ XW_Instance xw_instance = instance->xw_instance_;
+ if (!(xw_instance > 0 && xw_instance < next_xw_instance_)) {
+ LoggerW("xw_instance (%d) is invalid.", xw_instance);
+ return;
+ }
+ if (instance_map_.find(xw_instance) != instance_map_.end())
+ instance_map_.erase(xw_instance);
+}
+
+const void* ExtensionAdapter::GetInterface(const char* name) {
+ if (!strcmp(name, XW_CORE_INTERFACE_1)) {
+ static const XW_CoreInterface_1 coreInterface1 = {
+ CoreSetExtensionName,
+ CoreSetJavaScriptAPI,
+ CoreRegisterInstanceCallbacks,
+ CoreRegisterShutdownCallback,
+ CoreSetInstanceData,
+ CoreGetInstanceData
+ };
+ return &coreInterface1;
+ }
+
+ if (!strcmp(name, XW_MESSAGING_INTERFACE_1)) {
+ static const XW_MessagingInterface_1 messagingInterface1 = {
+ MessagingRegister,
+ MessagingPostMessage
+ };
+ return &messagingInterface1;
+ }
+
+ if (!strcmp(name, XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1)) {
+ static const XW_Internal_SyncMessagingInterface_1
+ syncMessagingInterface1 = {
+ SyncMessagingRegister,
+ SyncMessagingSetSyncReply
+ };
+ return &syncMessagingInterface1;
+ }
+
+ if (!strcmp(name, XW_INTERNAL_ENTRY_POINTS_INTERFACE_1)) {
+ static const XW_Internal_EntryPointsInterface_1 entryPointsInterface1 = {
+ EntryPointsSetExtraJSEntryPoints
+ };
+ return &entryPointsInterface1;
+ }
+
+ if (!strcmp(name, XW_INTERNAL_RUNTIME_INTERFACE_1)) {
+ static const XW_Internal_RuntimeInterface_1 runtimeInterface1 = {
+ RuntimeGetStringVariable
+ };
+ return &runtimeInterface1;
+ }
+
+ if (!strcmp(name, XW_INTERNAL_PERMISSIONS_INTERFACE_1)) {
+ static const XW_Internal_PermissionsInterface_1 permissionsInterface1 = {
+ PermissionsCheckAPIAccessControl,
+ PermissionsRegisterPermissions
+ };
+ return &permissionsInterface1;
+ }
+
+ LoggerW("Interface '%s' is not supported.", name);
+ return NULL;
+}
+
+Extension* ExtensionAdapter::GetExtension(XW_Extension xw_extension) {
+ ExtensionAdapter* adapter = ExtensionAdapter::GetInstance();
+ ExtensionMap::iterator it = adapter->extension_map_.find(xw_extension);
+ if (it == adapter->extension_map_.end())
+ return NULL;
+ return it->second;
+}
+
+ExtensionInstance* ExtensionAdapter::GetExtensionInstance(
+ XW_Instance xw_instance) {
+ ExtensionAdapter* adapter = ExtensionAdapter::GetInstance();
+ InstanceMap::iterator it = adapter->instance_map_.find(xw_instance);
+ if (it == adapter->instance_map_.end())
+ return NULL;
+ return it->second;
+}
+
+#define CHECK(x, xw) \
+ if (!x) { \
+ LoggerW("Ignoring call. Invalid %s = %d", #xw, xw); \
+ return; \
+ }
+
+#define RETURN_IF_INITIALIZED(x) \
+ if (x->initialized_) \
+ return;
+
+void ExtensionAdapter::CoreSetExtensionName(XW_Extension xw_extension,
+ const char* name) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->name_ = name;
+}
+
+void ExtensionAdapter::CoreSetJavaScriptAPI(XW_Extension xw_extension,
+ const char* javascript_api) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->javascript_api_ = javascript_api;
+}
+
+void ExtensionAdapter::CoreRegisterInstanceCallbacks(XW_Extension xw_extension,
+ XW_CreatedInstanceCallback created,
+ XW_DestroyedInstanceCallback destroyed) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->created_instance_callback_ = created;
+ extension->destroyed_instance_callback_ = destroyed;
+}
+
+void ExtensionAdapter::CoreRegisterShutdownCallback(XW_Extension xw_extension,
+ XW_ShutdownCallback shutdown) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->shutdown_callback_ = shutdown;
+}
+
+void ExtensionAdapter::CoreSetInstanceData(XW_Instance xw_instance,
+ void* data) {
+ ExtensionInstance* instance = GetExtensionInstance(xw_instance);
+ CHECK(instance, xw_instance);
+ instance->instance_data_ = data;
+}
+
+void* ExtensionAdapter::CoreGetInstanceData(XW_Instance xw_instance) {
+ ExtensionInstance* instance = GetExtensionInstance(xw_instance);
+ if (instance)
+ return instance->instance_data_;
+ else
+ return NULL;
+}
+
+void ExtensionAdapter::MessagingRegister(XW_Extension xw_extension,
+ XW_HandleMessageCallback handle_message) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->handle_msg_callback_ = handle_message;
+}
+
+void ExtensionAdapter::MessagingPostMessage(XW_Instance xw_instance,
+ const char* message) {
+ ExtensionInstance* instance = GetExtensionInstance(xw_instance);
+ CHECK(instance, xw_instance);
+ instance->PostMessageToJS(message);
+}
+
+void ExtensionAdapter::SyncMessagingRegister(XW_Extension xw_extension,
+ XW_HandleSyncMessageCallback handle_sync_message) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+ extension->handle_sync_msg_callback_ = handle_sync_message;
+}
+
+void ExtensionAdapter::SyncMessagingSetSyncReply(XW_Instance xw_instance,
+ const char* reply) {
+ ExtensionInstance* instance = GetExtensionInstance(xw_instance);
+ CHECK(instance, xw_instance);
+ instance->SyncReplyToJS(reply);
+}
+
+void ExtensionAdapter::EntryPointsSetExtraJSEntryPoints(
+ XW_Extension xw_extension, const char** entry_points) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ RETURN_IF_INITIALIZED(extension);
+
+ for (int i=0; entry_points[i]; ++i) {
+ extension->entry_points_.push_back(std::string(entry_points[i]));
+ }
+}
+
+void ExtensionAdapter::RuntimeGetStringVariable(XW_Extension xw_extension,
+ const char* key,
+ char* value,
+ unsigned int value_len) {
+ Extension* extension = GetExtension(xw_extension);
+ CHECK(extension, xw_extension);
+ extension->GetRuntimeVariable(key, value, value_len);
+}
+
+int ExtensionAdapter::PermissionsCheckAPIAccessControl(
+ XW_Extension xw_extension, const char* api_name) {
+ Extension* extension = GetExtension(xw_extension);
+ if (extension)
+ return extension->CheckAPIAccessControl(api_name);
+ else
+ return XW_ERROR;
+}
+
+int ExtensionAdapter::PermissionsRegisterPermissions(XW_Extension xw_extension,
+ const char* perm_table) {
+ Extension* extension = GetExtension(xw_extension);
+ if (extension)
+ return extension->RegisterPermissions(perm_table);
+ else
+ return XW_ERROR;
+}
+
+} // namespace wrt
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_EXTENSION_EXTENSION_ADAPTER_H_
+#define WRT_EXTENSION_EXTENSION_ADAPTER_H_
+
+#include <map>
+
+#include "extension/extension.h"
+#include "extension/extension_instance.h"
+
+#include "extension/xwalk/XW_Extension.h"
+#include "extension/xwalk/XW_Extension_SyncMessage.h"
+#include "extension/xwalk/XW_Extension_EntryPoints.h"
+#include "extension/xwalk/XW_Extension_Runtime.h"
+#include "extension/xwalk/XW_Extension_Permissions.h"
+
+namespace wrt {
+
+class ExtensionAdapter {
+ public:
+ typedef std::map<XW_Extension, Extension*> ExtensionMap;
+ typedef std::map<XW_Instance, ExtensionInstance*> InstanceMap;
+
+ static ExtensionAdapter* GetInstance();
+
+ XW_Extension GetNextXWExtension();
+ XW_Instance GetNextXWInstance();
+
+ void RegisterExtension(Extension* extension);
+ void UnregisterExtension(Extension* extension);
+
+ void RegisterInstance(ExtensionInstance* instance);
+ void UnregisterInstance(ExtensionInstance* instance);
+
+ // Returns the correct struct according to interface asked. This is
+ // passed to external extensions in XW_Initialize() call.
+ static const void* GetInterface(const char* name);
+
+ private:
+ ExtensionAdapter();
+ virtual ~ExtensionAdapter();
+
+ static Extension* GetExtension(XW_Extension xw_extension);
+ static ExtensionInstance* GetExtensionInstance(XW_Instance xw_instance);
+
+ static void CoreSetExtensionName(XW_Extension xw_extension, const char* name);
+ static void CoreSetJavaScriptAPI(XW_Extension xw_extension,
+ const char* javascript_api);
+ static void CoreRegisterInstanceCallbacks(XW_Extension xw_extension,
+ XW_CreatedInstanceCallback created,
+ XW_DestroyedInstanceCallback destroyed);
+ static void CoreRegisterShutdownCallback(XW_Extension xw_extension,
+ XW_ShutdownCallback shutdown);
+ static void CoreSetInstanceData(XW_Instance xw_instance, void* data);
+ static void* CoreGetInstanceData(XW_Instance xw_instance);
+ static void MessagingRegister(XW_Extension xw_extension,
+ XW_HandleMessageCallback handle_message);
+ static void MessagingPostMessage(XW_Instance xw_instance,
+ const char* message);
+ static void SyncMessagingRegister(XW_Extension xw_extension,
+ XW_HandleSyncMessageCallback handle_sync_message);
+ static void SyncMessagingSetSyncReply(XW_Instance xw_instance,
+ const char* reply);
+ static void EntryPointsSetExtraJSEntryPoints(XW_Extension xw_extension,
+ const char** entry_points);
+ static void RuntimeGetStringVariable(XW_Extension xw_extension,
+ const char* key,
+ char* value,
+ unsigned int value_len);
+ static int PermissionsCheckAPIAccessControl(XW_Extension xw_extension,
+ const char* api_name);
+ static int PermissionsRegisterPermissions(XW_Extension xw_extension,
+ const char* perm_table);
+
+ ExtensionMap extension_map_;
+ InstanceMap instance_map_;
+
+ XW_Extension next_xw_extension_;
+ XW_Instance next_xw_instance_;
+};
+
+} // namespace wrt
+
+#endif // WRT_EXTENSION_EXTENSION_ADAPTER_H_
#include "extension/extension_instance.h"
+#include "extension/extension_adapter.h"
+#include "extension/xwalk/XW_Extension_SyncMessage.h"
+
+namespace wrt {
+
+ExtensionInstance::ExtensionInstance(Extension* extension,
+ XW_Instance xw_instance)
+ : extension_(extension),
+ xw_instance_(xw_instance),
+ instance_data_(NULL) {
+ ExtensionAdapter::GetInstance()->RegisterInstance(this);
+ XW_CreatedInstanceCallback callback = extension_->created_instance_callback_;
+ if (callback)
+ callback(xw_instance_);
+}
+
+ExtensionInstance::~ExtensionInstance() {
+ XW_DestroyedInstanceCallback callback =
+ extension_->destroyed_instance_callback_;
+ if (callback)
+ callback(xw_instance_);
+ ExtensionAdapter::GetInstance()->UnregisterInstance(this);
+}
+
+void ExtensionInstance::HandleMessage(const std::string& msg) {
+ XW_HandleMessageCallback callback = extension_->handle_msg_callback_;
+ if (callback)
+ callback(xw_instance_, msg.c_str());
+}
+
+void ExtensionInstance::HandleSyncMessage(const std::string& msg) {
+ XW_HandleSyncMessageCallback callback = extension_->handle_sync_msg_callback_;
+ if (callback) {
+ callback(xw_instance_, msg.c_str());
+ }
+}
+
+void ExtensionInstance::SetPostMessageCallback(MessageCallback callback) {
+ post_message_callback_ = callback;
+}
+
+void ExtensionInstance::SetSendSyncReplyCallback(MessageCallback callback) {
+ send_sync_reply_callback_ = callback;
+}
+
+void ExtensionInstance::PostMessageToJS(const std::string& msg) {
+ post_message_callback_(msg);
+}
+
+void ExtensionInstance::SyncReplyToJS(const std::string& reply) {
+ send_sync_reply_callback_(reply);
+}
+
+} // namespace wrt
#ifndef WRT_EXTENSION_EXTENSION_INSTANCE_H_
#define WRT_EXTENSION_EXTENSION_INSTANCE_H_
+#include <string>
+#include <functional>
+
+#include "extension/xwalk/XW_Extension.h"
+
namespace wrt {
+class Extension;
+
class ExtensionInstance {
public:
- ExtensionInstance();
+ typedef std::function<void(const std::string&)> MessageCallback;
+
+ ExtensionInstance(Extension* extension, XW_Instance xw_instance);
virtual ~ExtensionInstance();
+
+ void HandleMessage(const std::string& msg);
+ void HandleSyncMessage(const std::string& msg);
+
+ void SetPostMessageCallback(MessageCallback callback);
+ void SetSendSyncReplyCallback(MessageCallback callback);
+
+ private:
+ friend class ExtensionAdapter;
+
+ void PostMessageToJS(const std::string& msg);
+ void SyncReplyToJS(const std::string& reply);
+
+ Extension* extension_;
+ XW_Instance xw_instance_;
+ void* instance_data_;
+
+ MessageCallback post_message_callback_;
+ MessageCallback send_sync_reply_callback_;
};
} // namespace wrt
+++ /dev/null
-// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extension/extension_manager.h"
+++ /dev/null
-// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WRT_EXTENSION_EXTENSION_MANAGER_H_
-#define WRT_EXTENSION_EXTENSION_MANAGER_H_
-
-namespace wrt {
-
-class ExtensionManager {
- public:
- ExtensionManager();
- virtual ~ExtensionManager();
-};
-
-} // namespace wrt
-
-#endif // WRT_EXTENSION_EXTENSION_MANAGER_H_
#include "extension/extension_server.h"
-ExtensionServer::ExtensionServer() {
+#include <Elementary.h>
+#include <glob.h>
+#include <string>
+#include <vector>
+
+#include "common/logger.h"
+#include "common/file_utils.h"
+#include "common/message_types.h"
+#include "common/picojson.h"
+#include "extension/extension.h"
+
+namespace wrt {
+
+namespace {
+const char kExtensionDir[] = "/usr/lib/tizen-extensions-crosswalk";
+const char kExtensionPrefix[] = "lib";
+const char kExtensionSuffix[] = ".so";
+} // namespace
+
+ExtensionServer::ExtensionServer(Ewk_Context* ewk_context)
+ : ewk_context_(ewk_context) {
}
ExtensionServer::~ExtensionServer() {
}
-void ExtensionServer::AddExtensionPath(const std::string& path) {
- extension_paths_.push_back(path);
+void ExtensionServer::RegisterExtension(const std::string& path) {
+ Extension* ext = new Extension(path, this);
+ if (!ext->Initialize() || !RegisterSymbols(ext)) {
+ delete ext;
+ }
+ extensions_[ext->name()] = ext;
+}
+
+void ExtensionServer::RegisterSystemExtensions() {
+ std::string extension_path(kExtensionDir);
+ extension_path.append("/");
+ extension_path.append(kExtensionPrefix);
+ extension_path.append("*");
+ extension_path.append(kExtensionSuffix);
+
+ glob_t glob_result;
+ glob(extension_path.c_str(), GLOB_TILDE, NULL, &glob_result);
+ for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) {
+ RegisterExtension(glob_result.gl_pathv[i]);
+ }
+}
+
+bool ExtensionServer::RegisterSymbols(Extension* extension) {
+ std::string name = extension->name();
+
+ if (extension_symbols_.find(name) != extension_symbols_.end()) {
+ LoggerW("Ignoring extension with name already registred. '%s'",
+ name.c_str());
+ return false;
+ }
+
+ Extension::StringVector entry_points = extension->entry_points();
+ for (auto it = entry_points.begin(); it != entry_points.end(); ++it) {
+ if (extension_symbols_.find(*it) != extension_symbols_.end()) {
+ LoggerW("Ignoring extension with entry_point already registred. '%s'",
+ (*it).c_str());
+ return false;
+ }
+ }
+
+ for (auto it = entry_points.begin(); it != entry_points.end(); ++it) {
+ extension_symbols_.insert(*it);
+ }
+
+ extension_symbols_.insert(name);
+
+ return true;
+}
+
+void ExtensionServer::AddRuntimeVariable(const std::string& key,
+ const std::string& value) {
+ runtime_variables_.insert(std::make_pair(key, value));
}
+
+void ExtensionServer::ClearRuntimeVariables() {
+ runtime_variables_.clear();
+}
+
+void ExtensionServer::GetRuntimeVariable(const char* key, char* value,
+ size_t value_len) {
+ auto it = runtime_variables_.find(key);
+ if (it != runtime_variables_.end()) {
+ strncpy(value, it->second.c_str(), value_len);
+ }
+}
+
+void ExtensionServer::Start() {
+ Start(StringVector());
+}
+
+void ExtensionServer::Start(const StringVector& paths) {
+ // Register system extensions to support Tizen Device APIs
+ RegisterSystemExtensions();
+
+ // Register user extensions
+ for (auto it = paths.begin(); it != paths.end(); ++it) {
+ if (utils::Exists(*it)) {
+ RegisterExtension(*it);
+ }
+ }
+
+ // Send 'ready' signal to Injected Bundle.
+ SendWrtMessage(message_types::kExtensionEPCreated);
+}
+
+void ExtensionServer::HandleWrtMessage(Ewk_IPC_Wrt_Message_Data* message) {
+ if (!message) {
+ LoggerW("Message object is NULL.");
+ return;
+ }
+
+ if (!ewk_context_) {
+ LoggerW("Ewk_Context is NULL.");
+ return;
+ }
+
+ Eina_Stringshare* msg_id = ewk_ipc_wrt_message_data_id_get(message);
+ Eina_Stringshare* msg_reference_id
+ = ewk_ipc_wrt_message_data_reference_id_get(message);
+ Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(message);
+ Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(message);
+
+ Ewk_IPC_Wrt_Message_Data* reply = ewk_ipc_wrt_message_data_new();
+
+ #define START_WITHS(x, s) (strncmp(x, s, strlen(s)) == 0)
+ if (START_WITHS(msg_type, message_types::kExtensionGetExtensions)) {
+ OnGetExtensions(msg_id);
+ } else if (START_WITHS(msg_type, message_types::kExtensionCreateInstance)) {
+ OnCreateInstance(msg_reference_id, msg_value);
+ } else if (START_WITHS(msg_type, message_types::kExtensionDestroyInstance)) {
+ OnDestroyInstance(msg_reference_id);
+ } else if (START_WITHS(msg_type, message_types::kExtensionCallSync)) {
+ OnSendSyncMessageToNative(msg_id, msg_reference_id, msg_value);
+ } else if (START_WITHS(msg_type, message_types::kExtensionCallAsync)) {
+ OnPostMessageToNative(msg_reference_id, msg_value);
+ }
+
+ eina_stringshare_del(msg_id);
+ eina_stringshare_del(msg_reference_id);
+ eina_stringshare_del(msg_type);
+ eina_stringshare_del(msg_value);
+ ewk_ipc_wrt_message_data_del(reply);
+
+ #undef START_WITHS
+}
+
+void ExtensionServer::SendWrtMessage(const std::string& type) {
+ SendWrtMessage(type, std::string(), std::string(), std::string());
+}
+
+void ExtensionServer::SendWrtMessage(
+ const std::string& type, const std::string& id,
+ const std::string& ref_id, const std::string& value) {
+ if (!ewk_context_) {
+ LoggerW("Ewk_Context is NULL.");
+ return;
+ }
+ Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new();
+ ewk_ipc_wrt_message_data_type_set(msg, type.c_str());
+ ewk_ipc_wrt_message_data_id_set(msg, id.c_str());
+ ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str());
+ ewk_ipc_wrt_message_data_value_set(msg, value.c_str());
+ if (!ewk_ipc_wrt_message_send(ewk_context_, msg)) {
+ LoggerE("Failed to send message to injected bundle.");
+ }
+ ewk_ipc_wrt_message_data_del(msg);
+}
+
+void ExtensionServer::OnGetExtensions(const std::string& id) {
+ picojson::array ext_array = picojson::array(0);
+ for (auto it = extensions_.begin(); it != extensions_.end(); ++it) {
+ picojson::object ext_obj = picojson::object();
+ ext_obj["name"] = picojson::value(it->second->name());
+ ext_obj["javascript_api"] = picojson::value(it->second->javascript_api());
+ ext_obj["entry_points"] = picojson::value(picojson::array(0));
+ picojson::array ext_ep_array
+ = ext_obj["entry_points"].get<picojson::array>();
+ Extension::StringVector entry_points = it->second->entry_points();
+ for (auto it_ep = entry_points.begin();
+ it_ep != entry_points.end(); ++it_ep) {
+ ext_ep_array.push_back(picojson::value(*it_ep));
+ }
+ ext_array.push_back(picojson::value(ext_obj));
+ }
+
+ picojson::value reply(ext_array);
+ SendWrtMessage(message_types::kExtensionGetExtensions,
+ std::string(), id, reply.serialize());
+}
+
+void ExtensionServer::OnCreateInstance(
+ const std::string& instance_id, const std::string& extension_name) {
+ // find extension with given name
+ auto it = extensions_.find(extension_name);
+ if (it == extensions_.end()) {
+ LoggerE("Can't find extension [%s].", extension_name.c_str());
+ return;
+ }
+
+ // create instance
+ ExtensionInstance* instance = it->second->CreateInstance();
+ if (!instance) {
+ LoggerE("Can't create instance of extension [%s].", extension_name.c_str());
+ return;
+ }
+
+ // Set PostMessageCallback / SendSyncReplyCallback
+ using std::placeholders::_1;
+ instance->SetPostMessageCallback(
+ std::bind(&ExtensionServer::OnPostMessageToJS, this, instance_id, _1));
+ instance->SetSendSyncReplyCallback(
+ std::bind(&ExtensionServer::OnSendSyncReplyToJS, this, instance_id, _1));
+
+ instances_[instance_id] = instance;
+}
+
+void ExtensionServer::OnDestroyInstance(const std::string& instance_id) {
+ auto it = instances_.find(instance_id);
+ if (it == instances_.end()) {
+ LoggerE("Can't find instance [%s].", instance_id.c_str());
+ return;
+ }
+
+ ExtensionInstance* instance = it->second;
+ delete instance;
+
+ instances_.erase(it);
+}
+
+void ExtensionServer::OnSendSyncMessageToNative(
+ const std::string& msg_id, const std::string& instance_id,
+ const std::string& msg_body) {
+ auto it = instances_.find(instance_id);
+ if (it == instances_.end()) {
+ LoggerE("Can't find instance [%s].", instance_id.c_str());
+ SendWrtMessage(message_types::kExtensionCallSync, "", msg_id, "ERROR");
+ return;
+ }
+
+ ExtensionInstance* instance = it->second;
+ instance->HandleSyncMessage(msg_body);
+}
+
+void ExtensionServer::OnPostMessageToNative(
+ const std::string& instance_id, const std::string& msg_body) {
+ auto it = instances_.find(instance_id);
+ if (it == instances_.end()) {
+ LoggerE("Can't find instance [%s].", instance_id.c_str());
+ return;
+ }
+
+ ExtensionInstance* instance = it->second;
+ instance->HandleMessage(msg_body);
+}
+
+void ExtensionServer::OnPostMessageToJS(
+ const std::string& instance_id, const std::string& msg) {
+ SendWrtMessage(message_types::kExtensionPostMessageToJS,
+ "", instance_id, msg);
+}
+
+void ExtensionServer::OnSendSyncReplyToJS(
+ const std::string& instance_id, const std::string& msg) {
+ SendWrtMessage(message_types::kExtensionCallSync,
+ "", instance_id, msg);
+}
+
+} // namespace wrt
#ifndef WRT_EXTENSION_EXTENSION_SERVER_H_
#define WRT_EXTENSION_EXTENSION_SERVER_H_
+#include <ewk_ipc_message.h>
+
#include <string>
+#include <set>
+#include <map>
#include <vector>
-#include "extensin/extension_manager.h"
+#include "extension/extension.h"
+
+class Ewk_Context;
namespace wrt {
-class ExtensionServer {
+class ExtensionServer : public Extension::ExtensionDelegate {
public:
- ExtensionServer();
+ typedef std::vector<std::string> StringVector;
+
+ explicit ExtensionServer(Ewk_Context* ewk_context);
virtual ~ExtensionServer();
- // 'path' can indicate a file or a directory.
- // if the 'path' indicate a directory, ExtensionServer will load all of
- // extensions in the directory.
- void AddExtensionPath(const std::string& path);
+ void Start();
+ void Start(const StringVector& paths);
+
+ void HandleWrtMessage(Ewk_IPC_Wrt_Message_Data* message);
+
private:
- std::vector<std::string> extension_paths_;
- ExtensionManager extension_manager_;
+ void RegisterExtension(const std::string& path);
+ void RegisterSystemExtensions();
+ bool RegisterSymbols(Extension* extension);
+
+ void AddRuntimeVariable(const std::string& key, const std::string& value);
+ void GetRuntimeVariable(const char* key, char* value, size_t value_len);
+ void ClearRuntimeVariables();
+
+ void SendWrtMessage(const std::string& type);
+ void SendWrtMessage(const std::string& type, const std::string& id,
+ const std::string& ref_id, const std::string& value);
+
+ void OnGetExtensions(const std::string& id);
+ void OnCreateInstance(const std::string& instance_id,
+ const std::string& extension_name);
+ void OnDestroyInstance(const std::string& instance_id);
+ void OnSendSyncMessageToNative(const std::string& msg_id,
+ const std::string& instance_id,
+ const std::string& msg_body);
+ void OnPostMessageToNative(const std::string& instance_id,
+ const std::string& msg_body);
+
+ void OnPostMessageToJS(const std::string& instance_id,
+ const std::string& msg);
+ void OnSendSyncReplyToJS(const std::string& instance_id,
+ const std::string& msg);
+
+ Ewk_Context* ewk_context_;
+
+ typedef std::set<std::string> StringSet;
+ StringSet extension_symbols_;
+
+ typedef std::map<std::string, std::string> StringMap;
+ StringMap runtime_variables_;
+
+ typedef std::map<std::string, Extension*> ExtensionMap;
+ ExtensionMap extensions_;
+
+ typedef std::map<std::string, ExtensionInstance*> InstanceMap;
+ InstanceMap instances_;
};
} // namespace wrt
--- /dev/null
+// 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_
--- /dev/null
+// 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_
+
--- /dev/null
+// 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_
--- /dev/null
+// 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,
+ unsigned int value_len);
+};
+
+typedef struct XW_Internal_RuntimeInterface_1
+ XW_Internal_RuntimeInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+
--- /dev/null
+// 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_
ADD_DEFINITIONS(${TARGET_RUNTIME_CFLAGS})
ADD_EXECUTABLE(${TARGET_RUNTIME} ${TARGET_RUNTIME_SRCS})
TARGET_LINK_LIBRARIES(${TARGET_RUNTIME}
- "-Wl,--whole-archive"
${TARGET_COMMON_STATIC}
- "-Wl,--no-whole-archive"
+ ${TARGET_EXTENSION_STATIC}
${TARGET_RUNTIME_LIBS}
${TARGET_RUNTIME_LDFLAGS}
)
#include <algorithm>
#include <memory>
+#include "common/message_types.h"
#include "runtime/native_window.h"
#include "runtime/command_line.h"
#include "runtime/web_view.h"
#include "runtime/vibration_manager.h"
namespace {
-
// TODO(sngn.lee) : It should be declare in common header
const char* kKeyNameBack = "back";
"\n"
"for (var i=0; i < window.frames.length; i++)\n"
"{ window.frames[i].document.dispatchEvent(__event); }";
-
} // namespace
namespace wrt {
WebApplication::WebApplication(const std::string& appid)
: initialized_(false),
- appid_(appid), ewk_context_(ewk_context_new()) {
+ appid_(appid),
+ ewk_context_(ewk_context_new()) {
+ // app_data_path
std::unique_ptr<char, decltype(std::free)*>
path {app_get_data_path(), std::free};
app_data_path_ = path.get();
+
+ // extension_server
+ extension_server_ = new ExtensionServer(ewk_context_);
}
WebApplication::~WebApplication() {
ewk_context_delete(ewk_context_);
+ if (extension_server_)
+ delete extension_server_;
}
bool WebApplication::Initialize(NativeWindow* window) {
window_ = window;
+ // start extension server
+ if (extension_server_)
+ extension_server_->Start();
+
// ewk setting
ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER);
void WebApplication::OnReceivedWrtMessage(
- WebView* view,
- const Ewk_IPC_Wrt_Message_Data& message) {
- // TODO(wy80.choi): To be implemented
+ WebView* /*view*/,
+ Ewk_IPC_Wrt_Message_Data* message) {
+
+ Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(message);
+
+ #define START_WITHS(x, s) (strncmp(x, s, strlen(s)) == 0)
+
+ if (START_WITHS(msg_type, message_types::kExtensionTypePrefix)) {
+ extension_server_->HandleWrtMessage(message);
+ }
+
+ // TODO(wy80.choi): handle other message type?
+ // changeUserAgent, clearAllCookie, GetWindowID, hide, exit, blockedUrl
+
+
+ #undef START_WITHS
}
void WebApplication::OnOrientationLock(WebView* view,
#include <list>
#include "runtime/web_view.h"
+#include "extension/extension_server.h"
class Ewk_Context;
virtual void OnClosedWebView(WebView * view);
virtual void OnRendered(WebView* view);
virtual void OnReceivedWrtMessage(WebView* view,
- const Ewk_IPC_Wrt_Message_Data& message);
+ Ewk_IPC_Wrt_Message_Data* message);
virtual void OnOrientationLock(WebView* view,
bool lock,
int preferred_rotation);
std::string appid_;
Ewk_Context* ewk_context_;
NativeWindow* window_;
+ ExtensionServer* extension_server_;
std::list<WebView*> view_stack_;
std::string app_data_path_;
};
Ewk_IPC_Wrt_Message_Data* msg =
static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
if (self->listener_)
- self->listener_->OnReceivedWrtMessage(self, *msg);
+ self->listener_->OnReceivedWrtMessage(self, msg);
};
evas_object_smart_callback_add(ewk_view_,
"wrt,message",
virtual void OnHardwareKey(
WebView* /*view*/, const std::string& /*keyname*/) {}
virtual void OnReceivedWrtMessage(
- WebView* /*view*/, const Ewk_IPC_Wrt_Message_Data& /*msg*/) {}
+ WebView* /*view*/, Ewk_IPC_Wrt_Message_Data* /*msg*/) {}
virtual void OnOrientationLock(
WebView* /*view*/,
bool /*lock*/,