Implementation of IPC Asynchronous Message Support.
[platform/framework/web/wrt-plugins-common.git] / src / plugins-ipc-message / ipc_message_support.cpp
index fa36f8d..547efae 100644 (file)
@@ -33,7 +33,10 @@ static WKBundleRef s_injectedBundleRef = NULL;
 static unsigned  int s_xWindowHandle = 0;
 
 namespace {
-std::string toString(WKStringRef str)
+const char* const TIZEN_GET_WINDOW_HANDLE = "tizen://getWindowHandle";
+const char* const TIZEN_CLEAR_ALL_COOKIES = "tizen://clearAllCookies";
+
+static std::string toString(WKStringRef str)
 {
     if (WKStringIsEmpty(str)) {
         return std::string();
@@ -43,8 +46,121 @@ std::string toString(WKStringRef str)
     WKStringGetUTF8CString(str, buffer, size + 1);
     return buffer;
 }
+
+static std::string sendSyncMessage(const char* name, const char* body)
+{
+    WKStringRef nameWKString = WKStringCreateWithUTF8CString(name);
+    WKStringRef bodyWKString = NULL;
+    if (body) {
+        bodyWKString = WKStringCreateWithUTF8CString(body);
+    }
+    WKTypeRef retWKType = NULL;
+    WKBundlePostSynchronousMessage(s_injectedBundleRef,
+                                   nameWKString,
+                                   bodyWKString,
+                                   &retWKType);
+    WKRelease(nameWKString);
+    if (bodyWKString) {
+        WKRelease(bodyWKString);
+    }
+    if (retWKType) {
+        std::string retString = toString(static_cast<WKStringRef>(retWKType));
+        WKRelease(retWKType);
+        return retString;
+    } else {
+        return std::string();
+    }
+}
+
+static void sendPostMessage(const char* name, const char* body)
+{
+    WKStringRef nameWKString = WKStringCreateWithUTF8CString(name);
+    WKStringRef bodyWKString = NULL;
+    if (body) {
+        bodyWKString = WKStringCreateWithUTF8CString(body);
+    }
+    WKTypeRef retWKType = NULL;
+    WKBundlePostMessage(s_injectedBundleRef,
+                        nameWKString,
+                        bodyWKString);
+    WKRelease(nameWKString);
+    if (bodyWKString) {
+        WKRelease(bodyWKString);
+    }
+}
+
+static int sendAsyncMessage(const char* name, const char* body, AsyncReplyCallback replyCallback, void* data)
+{
+    using namespace IPCMessageSupport;
+
+    int handle = AsyncConnectionManager::instance().addConnection(AsyncConnectionPtr(new AsyncConnection(replyCallback, data)));
+
+    std::string strBody = body;
+    std::stringstream ss;
+
+    ss << handle;
+    strBody = ss.str() + "_" + strBody;
+
+    sendPostMessage(name, strBody.c_str());
+
+    return handle;
+}
+
+} // namespace
+
+
+namespace IPCMessageSupport {
+
+AsyncConnectionManager::~AsyncConnectionManager()
+{
+    m_connectionMap.clear();
+}
+
+AsyncConnectionManager &AsyncConnectionManager::instance()
+{
+    static AsyncConnectionManager instance;
+
+    return instance;
+}
+
+int AsyncConnectionManager::addConnection(AsyncConnectionPtr connection)
+{
+    static int latestHandle = -1;
+    int newHandle;
+
+    latestHandle++;
+    if (latestHandle < 0) latestHandle = 0;
+
+    newHandle = latestHandle;
+
+    m_connectionMap.insert(AsyncConnectionMap::value_type(newHandle, connection));
+
+    return newHandle;
 }
 
+bool AsyncConnectionManager::removeConnection(int handle)
+{
+    bool ret = (m_connectionMap.erase(handle) == 1);
+
+    return ret;
+}
+
+AsyncConnectionPtr AsyncConnectionManager::getConnection(int handle)
+{
+    AsyncConnectionMap::iterator iter = m_connectionMap.find(handle);
+
+    if (iter != m_connectionMap.end())
+    {
+        return iter->second;
+    }
+
+    return AsyncConnectionPtr();
+}
+
+
+} // namespace IPCMessageSupport
+
+
 void IPCMessageSupport::setWKBundleRef(WKBundleRef bundleRef)
 {
     LogDebug("setWKBundleRef called");
@@ -75,7 +191,8 @@ const char* IPCMessageSupport::sendMessageToUiProcess(
         return NULL;
     }
 
-    if (!strcmp(name, "tizen://getWindowHandle")) {
+    // tizen://getWindowHandle
+    if (!strcmp(name, TIZEN_GET_WINDOW_HANDLE)) {
         if (s_xWindowHandle == 0) {
             return NULL;
         } else {
@@ -86,26 +203,72 @@ const char* IPCMessageSupport::sendMessageToUiProcess(
         }
     }
 
-    WKStringRef bodyWKString = NULL;
-    WKStringRef nameWKString = WKStringCreateWithUTF8CString(name);
-    if (body) {
-        bodyWKString = WKStringCreateWithUTF8CString(body);
+    // tizen://clearAllCookies
+    if (!strcmp(name, TIZEN_CLEAR_ALL_COOKIES)) {
+        sendPostMessage(name, body);
+        return NULL;
     }
-    WKTypeRef retWKType = NULL;
-    WKBundlePostSynchronousMessage(s_injectedBundleRef,
-                                   nameWKString,
-                                   bodyWKString,
-                                   &retWKType);
-    WKRelease(nameWKString);
-    if (bodyWKString) {
-        WKRelease(bodyWKString);
+
+    return NULL;
+}
+
+int IPCMessageSupport::sendAsyncMessageToUiProcess(const char* name, const char* body, AsyncReplyCallback replyCallback, void* data)
+{
+    LogDebug("sendAsyncMessageToUiProcess called");
+
+    if (s_injectedBundleRef == NULL)
+    {
+        LogError("UI Process information isn't set");
+        return -1;
     }
-    if (retWKType) {
-        std::string retString = toString(static_cast<WKStringRef>(retWKType));
-        WKRelease(retWKType);
-        return strdup(retString.c_str());
-    } else {
+
+    if (name == NULL)
+    {
+        LogError("msg name is null!");
+        return -1;
+    }
+
+    if (body == NULL)
+    {
+        body = "";
+    }
+
+    LogDebug("name = [" << name << "]");
+    LogDebug("body = [" << body << "]");
+
+    return sendAsyncMessage(name, body, replyCallback, data);
+}
+
+void* IPCMessageSupport::ignoreAsyncMessageReply(int handle)
+{
+    LogDebug("ignoreAsyncMessageReply called");
+
+    AsyncConnectionPtr connection = AsyncConnectionManager::instance().getConnection(handle);
+
+    if (!connection)
+    {
         return NULL;
     }
-    return NULL;
+
+    AsyncConnectionManager::instance().removeConnection(handle);
+
+    return connection->data;
+}
+
+void IPCMessageSupport::replyAsyncMessageToWebProcess(Ewk_Context* ewkContext, int handle, const char* body)
+{
+    LogDebug("replyAsyncMessageToWebProcess called");
+
+    if (ewkContext == NULL)
+    {
+        return;
+    }
+
+    std::string strBody = (body) ? (body) : "";
+    std::stringstream ss;
+    ss << handle;
+
+    strBody = ss.str() + "_" + strBody;
+
+    ewk_context_message_post_to_injected_bundle(ewkContext, REPLY_ASYNC, strBody.c_str());
 }