Implements extension loader and server
authorWonYoung Choi <wy80.choi@samsung.com>
Thu, 9 Apr 2015 04:11:52 +0000 (13:11 +0900)
committerWonYoung Choi <wy80.choi@samsung.com>
Fri, 10 Apr 2015 04:15:10 +0000 (13:15 +0900)
Change-Id: I32c20f92568ba32d741ccaffb4bb7fe8d8cc92ae

33 files changed:
CMakeLists.txt
build/dolint.sh
packaging/wrt.spec
src/CMakeLists.txt
src/bundle/CMakeLists.txt [new file with mode: 0644]
src/bundle/injected_bundle.cc
src/common/CMakeLists.txt
src/common/file_utils.cc
src/common/file_utils.h
src/common/message_types.cc [new file with mode: 0644]
src/common/message_types.h [new file with mode: 0644]
src/common/picojson.h [new file with mode: 0644]
src/extension/CMakeLists.txt
src/extension/extension.cc
src/extension/extension.h
src/extension/extension_adapter.cc [new file with mode: 0644]
src/extension/extension_adapter.h [new file with mode: 0644]
src/extension/extension_instance.cc
src/extension/extension_instance.h
src/extension/extension_manager.cc [deleted file]
src/extension/extension_manager.h [deleted file]
src/extension/extension_server.cc
src/extension/extension_server.h
src/extension/xwalk/XW_Extension.h [new file with mode: 0644]
src/extension/xwalk/XW_Extension_EntryPoints.h [new file with mode: 0644]
src/extension/xwalk/XW_Extension_Permissions.h [new file with mode: 0644]
src/extension/xwalk/XW_Extension_Runtime.h [new file with mode: 0644]
src/extension/xwalk/XW_Extension_SyncMessage.h [new file with mode: 0644]
src/runtime/CMakeLists.txt
src/runtime/web_application.cc
src/runtime/web_application.h
src/runtime/web_view.cc
src/runtime/web_view.h

index f98c49e..2429ad6 100644 (file)
@@ -41,7 +41,7 @@ ENDIF(WAYLAND_SUPPORT)
 # 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
index 387a73b..4c08dd9 100755 (executable)
@@ -4,8 +4,14 @@ echo "############################# CPP LINT ##################################"
 
 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
index 12242ec..7ab4aca 100755 (executable)
@@ -74,3 +74,4 @@ rm -fr %{buildroot}
 %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
index 2b3c554..1667ca7 100644 (file)
@@ -5,4 +5,6 @@
 SET(BASE_SRCDIR ${PROJECT_SOURCE_DIR}/src)
 
 ADD_SUBDIRECTORY(common)
+ADD_SUBDIRECTORY(extension)
+ADD_SUBDIRECTORY(bundle)
 ADD_SUBDIRECTORY(runtime)
diff --git a/src/bundle/CMakeLists.txt b/src/bundle/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b3afd1e
--- /dev/null
@@ -0,0 +1,50 @@
+# 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
+)
+
+
index 1908ab9..73b49b2 100644 (file)
@@ -1,3 +1,36 @@
 // 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() {
+}
index 5023aee..69a41c8 100644 (file)
@@ -7,7 +7,8 @@ SET(TARGET_COMMON_STATIC_INCS
 )
 
 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})
index 950e649..02879aa 100644 (file)
@@ -11,7 +11,7 @@
 namespace wrt {
 namespace utils {
 
-bool Exist(const std::string& path) {
+bool Exists(const std::string& path) {
   return (access(path.c_str(), F_OK) != -1);
 }
 
index 9ef81dc..57beac9 100644 (file)
@@ -10,7 +10,7 @@
 namespace wrt {
 namespace utils {
 
-bool Exist(const std::string& path);
+bool Exists(const std::string& path);
 
 std::string BaseName(const std::string& path);
 
diff --git a/src/common/message_types.cc b/src/common/message_types.cc
new file mode 100644 (file)
index 0000000..80185ac
--- /dev/null
@@ -0,0 +1,22 @@
+// 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
diff --git a/src/common/message_types.h b/src/common/message_types.h
new file mode 100644 (file)
index 0000000..827890d
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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_
diff --git a/src/common/picojson.h b/src/common/picojson.h
new file mode 100644 (file)
index 0000000..48bb64e
--- /dev/null
@@ -0,0 +1,1010 @@
+/*
+ * 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
index e69de29..754a4e8 100644 (file)
@@ -0,0 +1,27 @@
+# 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}
+)
index 8158d9a..bbf92c9 100644 (file)
@@ -4,14 +4,96 @@
 
 #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
 
index 025c2e6..ce8ac9c 100644 (file)
@@ -8,23 +8,79 @@
 #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
diff --git a/src/extension/extension_adapter.cc b/src/extension/extension_adapter.cc
new file mode 100644 (file)
index 0000000..36a9cd9
--- /dev/null
@@ -0,0 +1,274 @@
+// 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
diff --git a/src/extension/extension_adapter.h b/src/extension/extension_adapter.h
new file mode 100644 (file)
index 0000000..d098923
--- /dev/null
@@ -0,0 +1,86 @@
+// 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_
index 992ecaf..a50345c 100644 (file)
@@ -4,3 +4,57 @@
 
 #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
index c23d26f..be77669 100644 (file)
@@ -5,12 +5,40 @@
 #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
diff --git a/src/extension/extension_manager.cc b/src/extension/extension_manager.cc
deleted file mode 100644 (file)
index 015bd48..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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"
diff --git a/src/extension/extension_manager.h b/src/extension/extension_manager.h
deleted file mode 100644 (file)
index b42028c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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_
index 71251de..f50f16b 100644 (file)
 
 #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
index 38571cf..b6e85d7 100644 (file)
@@ -5,25 +5,72 @@
 #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
diff --git a/src/extension/xwalk/XW_Extension.h b/src/extension/xwalk/XW_Extension.h
new file mode 100644 (file)
index 0000000..174915a
--- /dev/null
@@ -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/src/extension/xwalk/XW_Extension_EntryPoints.h b/src/extension/xwalk/XW_Extension_EntryPoints.h
new file mode 100644 (file)
index 0000000..54532a9
--- /dev/null
@@ -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/src/extension/xwalk/XW_Extension_Permissions.h b/src/extension/xwalk/XW_Extension_Permissions.h
new file mode 100644 (file)
index 0000000..d25484e
--- /dev/null
@@ -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/src/extension/xwalk/XW_Extension_Runtime.h b/src/extension/xwalk/XW_Extension_Runtime.h
new file mode 100644 (file)
index 0000000..11ad307
--- /dev/null
@@ -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,
+                                   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_
+
diff --git a/src/extension/xwalk/XW_Extension_SyncMessage.h b/src/extension/xwalk/XW_Extension_SyncMessage.h
new file mode 100644 (file)
index 0000000..4eddbf9
--- /dev/null
@@ -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_
index 54f0ea0..6ad9328 100755 (executable)
@@ -59,9 +59,8 @@ INCLUDE_DIRECTORIES(${TARGET_RUNTIME_INCS})
 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}
 )
index 2219fb2..0973e84 100755 (executable)
 #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";
 
@@ -35,26 +35,36 @@ namespace {
         "\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);
 
@@ -213,9 +223,22 @@ void WebApplication::OnRendered(WebView* view) {
 
 
 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,
index de70161..83c2a12 100755 (executable)
@@ -9,6 +9,7 @@
 #include <list>
 
 #include "runtime/web_view.h"
+#include "extension/extension_server.h"
 
 class Ewk_Context;
 
@@ -33,7 +34,7 @@ class WebApplication : public WebView::EventListener {
   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);
@@ -47,6 +48,7 @@ class WebApplication : public WebView::EventListener {
   std::string appid_;
   Ewk_Context* ewk_context_;
   NativeWindow* window_;
+  ExtensionServer* extension_server_;
   std::list<WebView*> view_stack_;
   std::string app_data_path_;
 };
index 5fa3e32..5798616 100755 (executable)
@@ -273,7 +273,7 @@ void WebView::Initialize() {
     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",
index 57882bf..2dd0ee9 100755 (executable)
@@ -34,7 +34,7 @@ class WebView {
     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*/,