INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/include
- ${CMAKE_SOURCE_DIR}/src/legacy_support
)
INCLUDE(FindPkgConfig)
IF (with_websocket)
ADD_DEFINITIONS("-DWEBSOCKET")
SET(SRCS ${SRCS}
- src/legacy_support/websocket.cpp
- src/legacy_support/web_helper_agent.cpp)
+ src/websocket.cpp
+ src/web_helper_agent.cpp)
SET(PKGS_CHECK_MODULES ${PKGS_CHECK_MODULES} libwebsockets)
ENDIF(with_websocket)
+++ /dev/null
-/*
- * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdio.h>
-#include <dlog.h>
-
-#include "web_helper_agent.h"
-
-#include "websocket.h"
-#include "sclcoreimpl.h"
-
-using namespace scl;
-
-typedef struct {
- int major_version;
- WEB_HELPER_AGENT_TYPE agent_type;
-} WEB_HELPER_AGENT_TYPES_FOR_VERSIONS;
-
-static WEB_HELPER_AGENT_TYPES_FOR_VERSIONS web_helper_agent_types_for_versions[] = {
- {1, WEB_HELPER_AGENT_WEBSOCKET}, /* Major version 1 indicates that it uses websocket for communication */
-};
-
-static int WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM = \
- sizeof(web_helper_agent_types_for_versions) / sizeof(WEB_HELPER_AGENT_TYPES_FOR_VERSIONS);
-
-WEB_HELPER_AGENT_TYPE CWebHelperAgent::get_web_helper_agent_type_from_major_version(int version)
-{
- for (int loop = 0;loop < WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM;loop++) {
- if (web_helper_agent_types_for_versions[loop].major_version == version) {
- return web_helper_agent_types_for_versions[loop].agent_type;
- }
- }
- return WEB_HELPER_AGENT_UNKNOWN;
-}
-
-CWebHelperAgent* CWebHelperAgent::create_web_helper_agent(WEB_HELPER_AGENT_TYPE type)
-{
- CWebHelperAgent *ret = NULL;
- if (type == WEB_HELPER_AGENT_WEBSOCKET) {
- ret = new CWebHelperAgentWebSocket;
- }
- return ret;
-}
-
-void CWebHelperAgent::destroy_web_helper_agent(CWebHelperAgent* agent)
-{
- if (agent) delete agent;
-}
-
-CWebHelperAgent::CWebHelperAgent()
-{
-}
-
-CWebHelperAgent::~CWebHelperAgent()
-{
-}
-
-bool CWebHelperAgent::init()
-{
- return true;
-}
-
-bool CWebHelperAgent::exit()
-{
- return true;
-}
-
-void CWebHelperAgent::signal(int sig)
-{
-}
-
-void CWebHelperAgent::log(const char *str)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- //impl->logise_log(str);
- }
-}
-
-void CWebHelperAgent::commit_string(const char *str)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->commit_string(-1, "", str);
- }
-}
-
-void CWebHelperAgent::update_preedit_string(const char *str)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->update_preedit_string(-1, "", str);
- }
-}
-
-void CWebHelperAgent::send_key_event(unsigned int key, unsigned int key_mask)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->send_key_event(-1, "", key, key_mask);
- }
-}
-
-void CWebHelperAgent::forward_key_event(unsigned int key)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->forward_key_event(-1, "", key, scim::SCIM_KEY_NullMask);
- }
-}
-
-void CWebHelperAgent::set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- SclSize portrait, landscape;
- portrait.width = portrait_width;
- portrait.height = portrait_height;
- landscape.width = landscape_width;
- landscape.height = landscape_height;
- impl->set_keyboard_size_hints(portrait, landscape);
- }
-}
-
-void CWebHelperAgent::set_selection(int start_index, int end_index)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->set_selection(start_index, end_index);
- }
-}
-
-void CWebHelperAgent::get_selection()
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- //impl->get_selection(-1, "", );
- }
-}
-
-void CWebHelperAgent::get_surrounding_text(int maxlen_before, int maxlen_after)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->get_surrounding_text("", maxlen_before, maxlen_after);
- }
-}
-
-void CWebHelperAgent::delete_surrounding_text(int offset, int len)
-{
- CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
- if (impl) {
- impl->delete_surrounding_text(offset, len);
- }
-}
-
-std::string CMagicKeyManager::get_magic_key()
-{
- static std::string current_magic_key;
-
- /* If we don't have magic key generated yet */
- if (current_magic_key.length() != MAGIC_KEY_LENGTH) {
- char magic_key[MAGIC_KEY_LENGTH + 1];
- /* We are going to generate a magic key that contains ascii characters in the range of '0' to 'z' */
- const char magic_key_range_lower = '0';
- const char magic_key_range_upper = 'Z';
-
- unsigned int seed = time(NULL);
- for (int loop = 0;loop < MAGIC_KEY_LENGTH;loop++) {
- magic_key[loop] = (rand_r(&seed) % (magic_key_range_upper - magic_key_range_lower)) + magic_key_range_lower;
- }
- magic_key[MAGIC_KEY_LENGTH] = '\0';
-
- current_magic_key = magic_key;
- }
-
- return current_magic_key;
-}
+++ /dev/null
-/*
- * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _WEB_HELPER_AGENT_H_
-#define _WEB_HELPER_AGENT_H_
-
-#define MAGIC_KEY_LENGTH 32
-#define VERSION_DELIMITER '.'
-#define VERSION_TOKEN_NUM 2 // We are expecting 2 version tokens : MAJOR and MINOR
-
-#include <string>
-#include <sstream>
-#include <vector>
-
-class CStringTokenizer
-{
-public:
- static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
- unsigned int loop = 0;
- unsigned int start = 0;
- for (loop = 0;loop < s.length();loop++) {
- if (s.at(loop) == delim) {
- std::string item = s.substr(start, loop - start);
- elems.push_back(item);
- start = loop + 1;
- }
- }
- std::string item = s.substr(start, loop - start);
- elems.push_back(item);
- return elems;
- }
-
- static std::vector<std::string> split(const std::string &s, char delim) {
- std::vector<std::string> elems;
- split(s, delim, elems);
- return elems;
- }
-};
-
-typedef enum {
- WEB_HELPER_AGENT_UNKNOWN,
- WEB_HELPER_AGENT_WEBSOCKET,
- WEB_HELPER_AGENT_DIRECT,
-} WEB_HELPER_AGENT_TYPE;
-
-class CMagicKeyManager
-{
-public:
- static std::string get_magic_key();
-};
-
-class CWebHelperAgent
-{
-public:
- CWebHelperAgent();
- virtual ~CWebHelperAgent();
-
- virtual bool init();
- virtual bool exit();
-
- virtual bool run() { return false; }
- virtual void signal(int sig);
-
- virtual void on_init() {}
- virtual void on_exit() {}
-
- virtual void on_focus_in(int ic) {}
- virtual void on_focus_out(int ic) {}
-
- virtual void on_show(int ic) {}
- virtual void on_hide(int ic) {}
-
- virtual void on_set_rotation(int degree) {}
-
- virtual void on_update_cursor_position(int ic, int cursor_pos) {}
- virtual void on_update_surrounding_text(int ic, const char *text, int cursor) {}
- virtual void on_update_selection(int ic, const char *text) {}
-
- virtual void on_set_language(unsigned int language) {}
-
- virtual void on_set_imdata(char *buf, unsigned int len) {}
- virtual void on_get_imdata(char **buf, unsigned int *len) {}
-
- virtual void on_set_return_key_type(unsigned int type) {}
- virtual void on_get_return_key_type(unsigned int *type) {}
-
- virtual void on_set_return_key_disable(unsigned int disabled) {}
- virtual void on_get_return_key_disable(unsigned int *disabled) {}
-
- virtual void on_set_layout(unsigned int layout) {}
- virtual void on_get_layout(unsigned int *layout) {}
-
- virtual void on_reset_input_context(int ic) {}
-
- virtual void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret) {}
-
-
- virtual void log(const char *str);
- virtual void commit_string(const char *str);
- virtual void update_preedit_string(const char *str);
- virtual void send_key_event(unsigned int key, unsigned int key_mask);
- virtual void forward_key_event(unsigned int key);
- virtual void set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height);
- virtual void set_selection(int start_index, int end_index);
- virtual void get_selection();
- virtual void get_surrounding_text(int maxlen_before, int maxlen_after);
- virtual void delete_surrounding_text(int offset, int len);
-
-public:
- static WEB_HELPER_AGENT_TYPE get_web_helper_agent_type_from_major_version(int version);
- static CWebHelperAgent* create_web_helper_agent(WEB_HELPER_AGENT_TYPE type);
- static void destroy_web_helper_agent(CWebHelperAgent* agent);
-};
-
-#endif // _WEB_HELPER_AGENT_H_
+++ /dev/null
-/*
- * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <Ecore.h>
-#include <Ecore_IMF.h>
-#include <dlog.h>
-
-#include "websocket.h"
-
-#include <syslog.h>
-#include <signal.h>
-
-#include <libwebsockets.h>
-
-#ifdef WAYLAND
-#define EFL_BETA_API_SUPPORT
-#include <Ecore_Wl2.h>
-#endif
-
-#define WEBSOCKET_PORT 7681
-
-#define RECVED_MESSAGE "recved"
-#define MESSAGE_LEFT "left"
-
-pthread_t g_ws_server_thread = (pthread_t)NULL;
-pthread_mutex_t g_ws_server_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-pthread_cond_t g_ws_query_condition = PTHREAD_COND_INITIALIZER;
-pthread_mutex_t g_ws_query_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-bool g_ws_server_exit = false;
-struct lws_context *g_ws_server_context = NULL;
-
-CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::m_current_instance = NULL;
-
-int force_exit = 0;
-
-enum protocols {
- /* always first */
- PROTOCOL_HTTP = 0,
-
- PROTOCOL_KEYBOARD,
-
- /* always last */
- MAX_PROTOCOL_COUNT
-};
-
-struct per_session_data__http {
- int fd;
-};
-
-static int callback_http(struct lws *wsi,
- enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
-{
- return 0;
-}
-
-struct per_session_data__keyboard {
- int session_id;
- int valid;
- int need_init;
- int initialized;
-};
-
-static int callback_keyboard(struct lws *wsi,
- enum lws_callback_reasons reason,
- void *user, void *in, size_t len);
-
-static struct lws_protocols protocols[] = {
- {
- "http-only",
- callback_http,
- sizeof(struct per_session_data__http),
- 0,
- },
- {
- "keyboard-protocol",
- callback_keyboard,
- sizeof(struct per_session_data__keyboard),
- 32,
- },
- { NULL, NULL, 0, 0 }
-};
-
-
-static int callback_client(struct lws *wsi,
- enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
-{
- switch (reason) {
- case LWS_CALLBACK_CLIENT_ESTABLISHED:
- LOGD("[ClientTest] Connection established");
- break;
-
- case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
- LOGD("[ClientTest] Connection error");
- break;
-
- case LWS_CALLBACK_CLOSED:
- LOGD("[ClientTest] Connection closed");
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-int test_client_connection(void)
-{
- struct lws_context *context = NULL;
- struct lws_context_creation_info context_info;
- struct lws_client_connect_info connect_info;
- struct lws *wsi = NULL;
-
- memset(&context_info, 0, sizeof context_info);
- memset(&connect_info, 0, sizeof(connect_info));
-
- const int protocols_num = sizeof(protocols) / sizeof(lws_protocols);
- static struct lws_protocols client_protocols[protocols_num];
-
- memcpy(&client_protocols, protocols, sizeof(protocols));
- for (int loop = 0; loop < protocols_num - 1; loop++) {
- client_protocols[loop].callback = callback_client;
- }
-
- context_info.port = CONTEXT_PORT_NO_LISTEN;
- context_info.protocols = protocols;
- context_info.gid = -1;
- context_info.uid = -1;
-
- context = lws_create_context(&context_info);
- LOGD("[ClientTest] create_context : %p", context);
- if (context == NULL) {
- return -1;
- }
-
- connect_info.address = "localhost";
- connect_info.port = WEBSOCKET_PORT;
- connect_info.path = "/";
- connect_info.context = context;
- connect_info.ssl_connection = 0;
- connect_info.host = connect_info.address;
- connect_info.origin = connect_info.address;
- connect_info.ietf_version_or_minus_one = -1;
- connect_info.protocol = "keyboard-protocol";
-
- wsi = lws_client_connect_via_info(&connect_info);
- LOGD("[ClientTest] wsi created : %p", wsi);
-
- if (wsi) {
- lws_service(context, 50);
- }
-
- lws_context_destroy(context);
-
- return 0;
-}
-
-static Ecore_Timer *g_flush_server_recv_buffer_timer = NULL;
-static std::string server_recv_buffer;
-static Eina_Bool flush_server_recv_buffer_func(void *user)
-{
- LOGD("flushing recv buffer");
- CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
- struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user;
-
- if (g_flush_server_recv_buffer_timer)
- ecore_timer_del(g_flush_server_recv_buffer_timer);
- g_flush_server_recv_buffer_timer = NULL;
-
- if (!agent || !pss) return ECORE_CALLBACK_CANCEL;
-
- pthread_mutex_lock(&g_ws_server_mutex);
- ISE_MESSAGE message = CISEMessageSerializer::deserialize(server_recv_buffer);
- server_recv_buffer.clear();
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
- /*
- if (message.values.at(0).compare(CMagicKeyManager::get_magic_key()) == 0) {
- LOGD("LOGIN successful, validating client");
- pss->valid = true;
- } else {
- LOGD("LOGIN failed, invalidating client");
- pss->valid = false;
- }
- */
- pss->valid = true;
-
- if (agent->initialized()) {
- pss->need_init = true;
- ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
- }
- }
-
- /* Ignore valid check since the magic key is not used anymore */
- if (!pss->valid) pss->valid = true;
-
- if (pss->valid) {
- pthread_mutex_lock(&g_ws_server_mutex);
- std::queue<ISE_MESSAGE>& messages = agent->get_recv_message_queue();
- messages.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- ecore_pipe_write(agent->get_message_pipe(), RECVED_MESSAGE, strlen(RECVED_MESSAGE));
-
- /* If we received reply message, let's send signal to wake up our main thread */
- if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
- pthread_mutex_lock(&g_ws_query_mutex);
- pthread_cond_signal(&g_ws_query_condition);
- pthread_mutex_unlock(&g_ws_query_mutex);
- }
- } else {
- LOGD("Ignoring data received since client is not valid %d", pss->session_id);
- }
-
- return ECORE_CALLBACK_CANCEL;
-}
-
-static int callback_keyboard(struct lws *wsi,
- enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
-{
- static int last_session_id = 0;
- const int bufsize = 512;
- int n = 0;
- unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + bufsize +
- LWS_SEND_BUFFER_POST_PADDING];
- unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
- struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user;
- CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
-
- switch (reason) {
- case LWS_CALLBACK_ESTABLISHED:
- pss->session_id = ++last_session_id;
- LOGD("LWS_CALLBACK_ESTABLISHED : %p %d", g_ws_server_context, pss->session_id);
- pss->valid = false;
- pss->need_init = false;
- pss->initialized = false;
- if (g_ws_server_context) {
- ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
- }
- break;
-
- case LWS_CALLBACK_CLOSED:
- LOGD("LWS_CALLBACK_CLOSED : %d", pss->session_id);
- break;
-
- case LWS_CALLBACK_SERVER_WRITEABLE:
- if (agent) {
- /* Ignore valid check since the magic key is not used anymore */
- if (!pss->valid) pss->valid = true;
-
- /* We allow data tranmission only if this client is guaranteed to be valid */
- if (pss->valid) {
- pthread_mutex_lock(&g_ws_server_mutex);
- std::queue<ISE_MESSAGE>& messages = agent->get_send_message_queue();
-
- if (pss->need_init && !pss->initialized) {
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT];
- std::string str = CISEMessageSerializer::serialize(message);
- SECURE_LOGD("SEND_WEBSOCKET_MESSAGE : %d %s", pss->session_id, str.c_str());
- n = snprintf((char *)p, bufsize, "%s", str.c_str());
- /* too small for partial */
- n = lws_write(wsi, p, n, LWS_WRITE_TEXT);
- pss->need_init = false;
- pss->initialized = true;
- } else {
- /* One write allowed per one writable callback */
- if (messages.size() > 0) {
- ISE_MESSAGE &message = messages.front();
- bool drop = false;
- if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT]) == 0) {
- if (pss->initialized) {
- drop = true;
- } else {
- pss->initialized = true;
- }
- }
- if (!drop) {
- std::string str = CISEMessageSerializer::serialize(message);
- SECURE_LOGD("SEND_WEBSOCKET_MESSAGE : %d %s", pss->session_id, str.c_str());
- n = snprintf((char *)p, bufsize, "%s", str.c_str());
- /* too small for partial */
- n = lws_write(wsi, p, n, LWS_WRITE_TEXT);
- }
- messages.pop();
- }
- }
- if (messages.size() > 0) {
- ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
- }
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (n < 0) {
- LOGE("ERROR %d writing to di socket %d", n, pss->session_id);
- }
-
- if (messages.size() > 0) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- }
- } else {
- LOGD("Rejecting data transmission since client is not valid : %d", pss->session_id);
- }
- }
- break;
-
- case LWS_CALLBACK_RECEIVE:
- if (in) {
- if (g_flush_server_recv_buffer_timer) {
- ecore_thread_main_loop_begin();
- ecore_timer_del(g_flush_server_recv_buffer_timer);
- g_flush_server_recv_buffer_timer = NULL;
- ecore_thread_main_loop_end();
- }
-
- std::string str = std::string((const char *)in, len);
- if (CISEMessageSerializer::valid(str)) {
- LOGD("A valid new message received, flush previous buffer");
- flush_server_recv_buffer_func((void*)pss);
- }
-
- pthread_mutex_lock(&g_ws_server_mutex);
- server_recv_buffer += str;
- SECURE_LOGD("RECEIVE callback : [%zu] [%s], [%s]", len, str.c_str(), server_recv_buffer.c_str());
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- ecore_thread_main_loop_begin();
- g_flush_server_recv_buffer_timer = ecore_timer_add(0.05, flush_server_recv_buffer_func, (void*)pss);
- SECURE_LOGD("flush timer registered : %p", g_flush_server_recv_buffer_timer);
- ecore_thread_main_loop_end();
- }
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-void *process_ws_server(void *data)
-{
- while (!force_exit && !g_ws_server_exit) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
-
- if (g_ws_server_context) {
- lws_service(g_ws_server_context, 50);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
- LOGD("process_ws_server exits now");
- return NULL;
-}
-
-void log_func(int level, const char *line)
-{
- if (line) {
- LOGD("LEVEL : %d , %s", level, line);
- }
-}
-
-CWebHelperAgentWebSocket::CWebHelperAgentWebSocket()
-{
- if (m_current_instance != NULL) {
- LOGD("WARNING : m_current_instance is NOT NULL");
- }
- m_current_instance = this;
- m_message_pipe = NULL;
- m_initialized = false;
-}
-
-CWebHelperAgentWebSocket::~CWebHelperAgentWebSocket()
-{
- if (m_current_instance == this) {
- m_current_instance = NULL;
- }
-
- if (m_message_pipe) {
- ecore_pipe_del(m_message_pipe);
- m_message_pipe = NULL;
- }
-}
-
-static void message_pipe_handler(void *data, void *buffer, unsigned int nbyte)
-{
- if (buffer) {
- if (strncmp((const char*)buffer, RECVED_MESSAGE, strlen(RECVED_MESSAGE)) == 0) {
- CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
- if (agent) {
- agent->process_recved_messages();
- }
- } else {
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
- }
-}
-
-bool CWebHelperAgentWebSocket::init()
-{
- bool ret = true;
-
- struct lws_context_creation_info info;
-
- memset(&info, 0, sizeof info);
- info.port = WEBSOCKET_PORT;
-
- int log_level = LLL_ERR | LLL_WARN | LLL_DEBUG;
- lws_set_log_level(log_level, log_func);
-
- info.iface = NULL;
- info.protocols = protocols;
- info.extensions = NULL;
- info.ssl_cert_filepath = NULL;
- info.ssl_private_key_filepath = NULL;
- info.gid = -1;
- info.uid = -1;
- info.options = 0;
-
- ecore_init();
-
- /* The WebSocket server is running on a separate thread, and let the thread send a message
- through this pipe to guarantee thread safety */
- m_message_pipe = ecore_pipe_add(message_pipe_handler, NULL);
-
- /* Let's retry creating server context for a certain number of times */
- const int max_retry_num = 30;
- int retry_num = 0;
-
- do {
- g_ws_server_context = lws_create_context(&info);
- LOGD("libwebsocket context : %p", g_ws_server_context);
- usleep(100 * 1000);
- } while (g_ws_server_context == NULL && retry_num++ < max_retry_num);
-
- pthread_mutex_init(&g_ws_server_mutex, NULL);
-
- pthread_mutex_init(&g_ws_query_mutex, NULL);
- pthread_cond_init(&g_ws_query_condition, NULL);
-
- m_initialized = true;
-
- return ret;
-}
-
-bool CWebHelperAgentWebSocket::exit()
-{
- if (g_flush_server_recv_buffer_timer)
- ecore_timer_del(g_flush_server_recv_buffer_timer);
- g_flush_server_recv_buffer_timer = NULL;
-
- on_exit();
-
- g_ws_server_exit = true;
- if (g_ws_server_context) {
- lws_cancel_service(g_ws_server_context);
- }
-
- if (m_message_pipe) {
- ecore_pipe_del(m_message_pipe);
- m_message_pipe = NULL;
- }
-
- if (g_ws_server_thread) {
- pthread_join(g_ws_server_thread, NULL);
- }
-
- pthread_cond_destroy(&g_ws_query_condition);
- pthread_mutex_destroy(&g_ws_query_mutex);
-
- pthread_mutex_destroy(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_context_destroy(g_ws_server_context);
- g_ws_server_context = NULL;
- }
-
- ecore_shutdown();
-
- return true;
-}
-
-bool CWebHelperAgentWebSocket::run()
-{
- if (!m_initialized) {
- LOGE("Not initialized");
- return false;
- }
-
- bool ret = false;
- if (g_ws_server_context) {
- if (pthread_create(&g_ws_server_thread, NULL, &process_ws_server, NULL) != 0) {
- g_ws_server_thread = (pthread_t)NULL;
- ret = false;
-
- on_init();
-
- test_client_connection();
- }
- } else {
- LOGE("Failed creating server context : %p", g_ws_server_context);
- ret = false;
- }
- return ret;
-}
-
-void CWebHelperAgentWebSocket::signal(int sig)
-{
- force_exit = 1;
-}
-
-template<class T>
-std::string to_string(T i)
-{
- std::stringstream ss;
- std::string s;
- ss << i;
- s = ss.str();
-
- return s;
-}
-
-void CWebHelperAgentWebSocket::on_init()
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_exit()
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_EXIT];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_focus_in(int ic)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_IN];
- message.values.push_back(to_string(ic));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_focus_out(int ic)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_OUT];
- message.values.push_back(to_string(ic));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_show(int ic)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SHOW];
- message.values.push_back(to_string(ic));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- LOGD("put into send message buffer");
-}
-
-void CWebHelperAgentWebSocket::on_hide(int ic)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_HIDE];
- message.values.push_back(to_string(ic));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_set_rotation(int degree)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_ROTATION];
- message.values.push_back(to_string(degree));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_update_cursor_position(int ic, int cursor_pos)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION];
- message.values.push_back(to_string(ic));
- message.values.push_back(to_string(cursor_pos));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_update_surrounding_text(int ic, const char *text, int cursor)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT];
- message.values.push_back(to_string(cursor));
- message.values.push_back(text);
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_update_selection(int ic, const char *text)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SELECTION];
- message.values.push_back(text);
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_set_language(unsigned int language)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LANGUAGE];
-
- bool found = false;
- for (unsigned int loop = 0;loop < sizeof(ISE_LANGUAGE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (language == (unsigned int)ISE_LANGUAGE_TYPES[loop].type_value) {
- message.values.push_back(ISE_LANGUAGE_TYPES[loop].type_string);
- found = true;
- }
- }
-
- if (found) {
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
-}
-
-void CWebHelperAgentWebSocket::on_set_imdata(char *buf, unsigned int len)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_IMDATA];
- message.values.push_back(buf);
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_get_imdata(char **buf, unsigned int *len)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- wait_for_reply_message();
-
- std::vector<std::string> values;
- /* Check if we received reply for GET_IMDATA message */
- if (process_recved_messages_until_reply_found(
- ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA], values)) {
- if (values.size() > 0 && buf && len) {
- int string_length = values.at(0).length();
- (*buf) = new char[string_length + 1];
- if (*buf) {
- strncpy(*buf, values.at(0).c_str(), string_length);
- /* Make sure this is a null-terminated string */
- *(*buf + string_length) = '\0';
- *len = string_length;
- }
- }
- } else {
- LOGD("process_recved_messages_until_reply_found returned FALSE");
- }
- /* Now process the rest in the recv buffer */
- process_recved_messages();
-}
-
-void CWebHelperAgentWebSocket::on_set_return_key_type(unsigned int type)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE];
-
- bool found = false;
- for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (type == (unsigned int)ISE_RETURN_KEY_TYPES[loop].type_value) {
- message.values.push_back(ISE_RETURN_KEY_TYPES[loop].type_string);
- found = true;
- }
- }
-
- if (found) {
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
-}
-
-void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- wait_for_reply_message();
-
- std::vector<std::string> values;
- /* Check if we received reply for GET_RETURN_KEY_TYPE message */
- if (process_recved_messages_until_reply_found(
- ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE], values)) {
- if (type) {
- for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (values.at(0).compare(ISE_RETURN_KEY_TYPES[loop].type_string) == 0) {
- *type = ISE_RETURN_KEY_TYPES[loop].type_value;
- }
- }
- }
- }
- /* Now process the rest in the recv buffer */
- process_recved_messages();
-}
-
-void CWebHelperAgentWebSocket::on_set_return_key_disable(unsigned int disabled)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE];
-
- bool found = false;
- for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (disabled == (unsigned int)ISE_TRUEFALSE_TYPES[loop].type_value) {
- message.values.push_back(ISE_TRUEFALSE_TYPES[loop].type_string);
- found = true;
- }
- }
-
- if (found) {
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
-}
-
-void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- wait_for_reply_message();
-
- std::vector<std::string> values;
- /* Check if we received reply for GET_RETURN_KEY_DISABLE message */
- if (process_recved_messages_until_reply_found(
- ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE], values)) {
- if (disabled) {
- for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
- *disabled = ISE_TRUEFALSE_TYPES[loop].type_value;
- }
- }
- }
- }
- /* Now process the rest in the recv buffer */
- process_recved_messages();
-}
-
-void CWebHelperAgentWebSocket::on_set_layout(unsigned int layout)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LAYOUT];
-
- bool found = false;
- for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (layout == (unsigned int)ISE_LAYOUT_TYPES[loop].type_value) {
- message.values.push_back(ISE_LAYOUT_TYPES[loop].type_string);
- found = true;
- }
- }
-
- if (found) {
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
-}
-
-void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT];
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- wait_for_reply_message();
-
- std::vector<std::string> values;
- /* Check if we received reply for GET_LAYOUT message */
- if (process_recved_messages_until_reply_found(
- ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT], values)) {
- if (layout) {
- for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (values.at(0).compare(ISE_LAYOUT_TYPES[loop].type_string) == 0) {
- *layout = ISE_LAYOUT_TYPES[loop].type_value;
- }
- }
- }
- }
- /* Now process the rest in the recv buffer */
- process_recved_messages();
-}
-
-void CWebHelperAgentWebSocket::on_reset_input_context(int ic)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT];
- message.values.push_back(to_string(ic));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-}
-
-void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret)
-{
- ISE_MESSAGE message;
- message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
- message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT];
- message.values.push_back(to_string(code));
- message.values.push_back(to_string(mask));
- message.values.push_back(to_string(layout));
-
- pthread_mutex_lock(&g_ws_server_mutex);
- m_send_message_queue.push(message);
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
-
- wait_for_reply_message();
-
- std::vector<std::string> values;
- /* Check if we received reply for PROCESS_KEY_EVENT message */
- if (process_recved_messages_until_reply_found(
- ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT], values)) {
- if (ret) {
- for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
- if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
- *ret = ISE_TRUEFALSE_TYPES[loop].type_value;
- }
- }
- }
- }
- /* Now process the rest in the recv buffer */
- process_recved_messages();
-}
-
-CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::get_current_instance()
-{
- return m_current_instance;
-}
-
-std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_send_message_queue()
-{
- return m_send_message_queue;
-}
-
-std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_recv_message_queue()
-{
- return m_recv_message_queue;
-}
-
-Ecore_Pipe* CWebHelperAgentWebSocket::get_message_pipe()
-{
- return m_message_pipe;
-}
-
-void CWebHelperAgentWebSocket::wait_for_reply_message()
-{
- /* Let's wait for at most REPLY_TIMEOUT */
- struct timeval now;
- struct timespec timeout;
- gettimeofday(&now, NULL);
- timeout.tv_sec = now.tv_sec + REPLY_TIMEOUT.tv_sec;
- timeout.tv_nsec = (now.tv_usec + REPLY_TIMEOUT.tv_usec) * 1000;
- pthread_mutex_lock(&g_ws_query_mutex);
- pthread_cond_timedwait(&g_ws_query_condition, &g_ws_query_mutex, &timeout);
- pthread_mutex_unlock(&g_ws_query_mutex);
-}
-
-void CWebHelperAgentWebSocket::process_recved_messages()
-{
- pthread_mutex_lock(&g_ws_server_mutex);
-
- while (m_recv_message_queue.size() > 0) {
- ISE_MESSAGE &message = m_recv_message_queue.front();
-
- handle_recved_message(message);
-
- m_recv_message_queue.pop();
- }
-
- pthread_mutex_unlock(&g_ws_server_mutex);
-}
-
-bool CWebHelperAgentWebSocket::process_recved_messages_until_reply_found(std::string command, std::vector<std::string> &values)
-{
- bool ret = false;
-
- pthread_mutex_lock(&g_ws_server_mutex);
-
- while (ret == false && m_recv_message_queue.size() > 0) {
- ISE_MESSAGE &message = m_recv_message_queue.front();
-
- if (message.command.compare(command) == 0 &&
- message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
- ret = true;
- values = message.values;
- }
- handle_recved_message(message);
-
- m_recv_message_queue.pop();
- }
-
- pthread_mutex_unlock(&g_ws_server_mutex);
-
- return ret;
-}
-
-void CWebHelperAgentWebSocket::handle_recved_message(ISE_MESSAGE &message)
-{
- static bool _key_event_processing = false;
- if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOG]) == 0) {
- std::string str = "";
- for (unsigned int loop = 0;loop < message.values.size();loop++) {
- str += message.values.at(loop).c_str();
- if (loop < message.values.size() - 1) {
- str += " ";
- }
- }
- log(str.c_str());
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_COMMIT_STRING]) == 0) {
- std::string str = "";
- for (unsigned int loop = 0;loop < message.values.size();loop++) {
- str += message.values.at(loop).c_str();
- if (loop < message.values.size() - 1) {
- str += " ";
- }
- }
- if (_key_event_processing) {
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 50000;
- select(0, NULL, NULL, NULL, &tv);
- _key_event_processing = false;
- }
- commit_string(str.c_str());
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING]) == 0) {
- std::string str = "";
- for (unsigned int loop = 0;loop < message.values.size();loop++) {
- str += message.values.at(loop).c_str();
- if (loop < message.values.size() - 1) {
- str += " ";
- }
- }
- update_preedit_string(str.c_str());
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SEND_KEY_EVENT]) == 0) {
- if (message.values.size() == 1) {
- forward_key_event(atoi(message.values.at(0).c_str()));
- _key_event_processing = true;
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES]) == 0) {
- LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES");
- int portrait_width, portrait_height;
- int landscape_width, landscape_height;
-
- if (message.values.size() == 4 || message.values.size() == 2) {
- portrait_width = atoi(message.values.at(0).c_str());
- portrait_height = atoi(message.values.at(1).c_str());
- if (message.values.size() == 2) {
- landscape_width = portrait_width;
- landscape_height = portrait_height;
- } else {
- landscape_width = atoi(message.values.at(2).c_str());
- landscape_height = atoi(message.values.at(3).c_str());
- }
-
- LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES : %d %d %d %d",
- portrait_width, portrait_height, landscape_width, landscape_height);
-
-#ifdef WAYLAND
- /* Since the full screen IME makes the client application fully obscured,
- * when it hides the client receives resume command and try to show IME again.
- * So here we are adjusting the height value when the requested keyboard size
- * is the same with the screen size, as a workaround */
- int scr_w = 0, scr_h = 0;
- ecore_wl2_sync();
- Ecore_Wl2_Display *ewd = NULL;
- if ((ewd = ecore_wl2_connected_display_get(NULL))) {
- ecore_wl2_display_screen_size_get(ewd, &scr_w, &scr_h);
-
- if (scr_w == portrait_width && scr_h == portrait_height) {
- portrait_height -= 1;
- }
- if (scr_h == landscape_width && scr_w == landscape_height) {
- landscape_height -= 1;
- }
- }
-#endif
-
- set_keyboard_sizes(
- portrait_width, portrait_height, landscape_width, landscape_height);
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_SELECTION]) == 0) {
- LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION");
- if (message.values.size() == 2) {
- LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION : %d %d",
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- set_selection(
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SELECTION]) == 0) {
- if (message.values.size() == 0) {
- get_selection();
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT]) == 0) {
- LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT");
- if (message.values.size() == 2) {
- LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT : %d %d",
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- get_surrounding_text(
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT]) == 0) {
- LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT");
- if (message.values.size() == 2) {
- LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT : %d %d",
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- delete_surrounding_text(
- atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
- }
- } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
- if (g_ws_server_context) {
- lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
- } else {
- LOGD("WARNING : g_ws_server_context is NULL");
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _WEB_HELPER_AGENT_WEBSOCKET_H_
-#define _WEB_HELPER_AGENT_WEBSOCKET_H_
-
-#include "web_helper_agent.h"
-
-#include <queue>
-
-#include <Ecore.h>
-#include <Eina.h>
-#include <Ecore_IMF.h>
-
-/* Wait for at most 1 second */
-const struct timeval REPLY_TIMEOUT = {1, 0};
-
-typedef enum {
- ISE_MESSAGE_TYPE_PLAIN,
- ISE_MESSAGE_TYPE_QUERY,
- ISE_MESSAGE_TYPE_REPLY,
-
- ISE_MESSAGE_TYPES_NUM,
-} ISE_MESSAGE_TYPES;
-
-const std::string ISE_MESSAGE_TYPE_STRINGS[] = {
- "plain", // ISE_MESSAGE_TYPE_PLAIN,
- "query", // ISE_MESSAGE_TYPE_QUERY
- "reply", // ISE_MESSAGE_TYPE_REPLY
-};
-
-typedef enum {
- ISE_MESSAGE_COMMAND_INIT,
- ISE_MESSAGE_COMMAND_EXIT,
-
- ISE_MESSAGE_COMMAND_FOCUS_IN,
- ISE_MESSAGE_COMMAND_FOCUS_OUT,
- ISE_MESSAGE_COMMAND_SHOW,
- ISE_MESSAGE_COMMAND_HIDE,
- ISE_MESSAGE_COMMAND_SET_ROTATION,
- ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION,
- ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT,
- ISE_MESSAGE_COMMAND_UPDATE_SELECTION,
- ISE_MESSAGE_COMMAND_SET_LANGUAGE,
- ISE_MESSAGE_COMMAND_SET_IMDATA,
- ISE_MESSAGE_COMMAND_GET_IMDATA,
- ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE,
- ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE,
- ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE,
- ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE,
- ISE_MESSAGE_COMMAND_SET_LAYOUT,
- ISE_MESSAGE_COMMAND_GET_LAYOUT,
- ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT,
- ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT,
-
- ISE_MESSAGE_COMMAND_LOG,
- ISE_MESSAGE_COMMAND_COMMIT_STRING,
- ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING,
- ISE_MESSAGE_COMMAND_SEND_KEY_EVENT,
- ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT,
- ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES,
- ISE_MESSAGE_COMMAND_SET_SELECTION,
- ISE_MESSAGE_COMMAND_GET_SELECTION,
- ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT,
- ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT,
- ISE_MESSAGE_COMMAND_LOGIN,
-
- ISE_MESSAGE_COMMANDS_NUM,
-} ISE_MESSAGE_COMMANDS;
-
-const std::string ISE_MESSAGE_COMMAND_STRINGS[] = {
- "init", // ISE_MESSAGE_COMMAND_INIT,
- "exit", // ISE_MESSAGE_COMMAND_EXIT,
-
- "focus_in", // ISE_MESSAGE_COMMAND_FOCUS_IN,
- "focus_out", // ISE_MESSAGE_COMMAND_FOCUS_OUT,
- "show", // ISE_MESSAGE_COMMAND_SHOW,
- "hide", // ISE_MESSAGE_COMMAND_HIDE,
- "set_rotation", // ISE_MESSAGE_COMMAND_SET_ROTATION,
- "update_cursor_position", // ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION,
- "update_surrounding_text", // ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT,
- "update_selection", // ISE_MESSAGE_COMMAND_UPDATE_SELECTION
- "set_language", // ISE_MESSAGE_COMMAND_SET_LANGUAGE,
- "set_imdata", // ISE_MESSAGE_COMMAND_SET_IMDATA,
- "get_imdata", // ISE_MESSAGE_COMMAND_GET_IMDATA,
- "set_return_key_type", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE,
- "get_return_key_type", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE,
- "set_return_key_disable", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE,
- "get_return_key_disable", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE,
- "set_layout", // ISE_MESSAGE_COMMAND_SET_LAYOUT,
- "get_layout", // ISE_MESSAGE_COMMAND_GET_LAYOUT,
- "reset_input_context", // ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT,
- "process_key_event", // ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT,
-
- "log", // ISE_MESSAGE_COMMAND_LOG,
- "commit_string", // ISE_MESSAGE_COMMAND_COMMIT_STRING,
- "update_preedit_string", // ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING,
- "send_key_event", // ISE_MESSAGE_COMMAND_SEND_KEY_EVENT,
- "forward_key_event", // ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT,
- "set_keyboard_sizes", // ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES,
- "set_selection", // ISE_MESSAGE_COMMAND_SET_SELECTION,
- "get_selection", // ISE_MESSAGE_COMMAND_GET_SELECTION,
- "get_surrounding_text", // ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT,
- "delete_surrounding_text", // ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT,
- "login", // ISE_MESSAGE_COMMAND_LOGIN,
-};
-
-typedef struct {
- std::string type;
- std::string command;
- std::vector<std::string> values;
-} ISE_MESSAGE;
-
-typedef struct {
- int type_value;
- std::string type_string;
-} ISE_TYPE_VALUE_STRING;
-
-const ISE_TYPE_VALUE_STRING ISE_RETURN_KEY_TYPES[] = {
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, "default"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE, "done"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO, "go"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, "join"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, "login"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, "next"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, "search"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND, "send"},
- {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN, "signin"},
-};
-
-const ISE_TYPE_VALUE_STRING ISE_LAYOUT_TYPES[] = {
- {ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, "normal"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER, "number"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL, "email"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_URL, "url"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER, "phonenumber"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_IP, "ip"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH, "month"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY, "numberonly"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD, "password"},
- {ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME, "datetime"},
-};
-
-const ISE_TYPE_VALUE_STRING ISE_LANGUAGE_TYPES[] = {
- {ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC, "automatic"},
- {ECORE_IMF_INPUT_PANEL_LANG_ALPHABET, "alphabet"},
-};
-
-/* FIXME : Should consider the case if the boolean value does not match with EINA_TRUE or EINA_FALSE */
-const ISE_TYPE_VALUE_STRING ISE_TRUEFALSE_TYPES[] = {
- {EINA_FALSE, "false"},
- {EINA_TRUE, "true"},
-};
-
-class CISEMessageSerializer
-{
-protected:
- /* FIXME : Temporary solution for distinguish commands and values */
- static const char MESSAGE_DELIMETER = ' ';
-
-public:
- static std::string serialize(ISE_MESSAGE message) {
- std::string ret;
- ret += message.type;
- ret += MESSAGE_DELIMETER;
- ret += message.command;
- for (unsigned int loop = 0;loop < message.values.size();loop++) {
- ret += MESSAGE_DELIMETER;
- ret += message.values.at(loop);
- }
- return ret;
- }
-
- static ISE_MESSAGE deserialize(std::string message) {
- ISE_MESSAGE ret;
- std::vector<std::string> vec = CStringTokenizer::split(message, MESSAGE_DELIMETER);
- if (vec.size() > 1) {
- ret.type = vec.at(0);
- vec.erase(vec.begin());
- ret.command = vec.at(0);
- vec.erase(vec.begin());
- ret.values = vec;
- }
- return ret;
- }
-
- static bool valid(std::string str)
- {
- int loop;
-
- bool valid_type = false;
- bool valid_command = false;
-
- ISE_MESSAGE message;
- message = deserialize(str);
-
- for (loop = 0;!valid_type && loop < ISE_MESSAGE_TYPES_NUM;loop++) {
- if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[loop]) == 0) {
- valid_type = true;
- }
- }
- for (loop = 0;!valid_command && loop < ISE_MESSAGE_COMMANDS_NUM;loop++) {
- if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[loop]) == 0) {
- valid_command = true;
- }
- }
-
- return (valid_type && valid_command);
- }
-};
-
-class CWebHelperAgentWebSocket : public CWebHelperAgent {
-public:
- CWebHelperAgentWebSocket();
- virtual ~CWebHelperAgentWebSocket();
-
- bool init();
- bool exit();
-
- bool run();
-
- bool initialized() { return m_initialized; }
-
- void signal(int sig);
-
- void on_init();
- void on_exit();
-
- void on_focus_in(int ic);
- void on_focus_out(int ic);
-
- void on_show(int ic);
- void on_hide(int ic);
-
- void on_set_rotation(int degree);
-
- void on_update_cursor_position(int ic, int cursor_pos);
- void on_update_surrounding_text(int ic, const char *text, int cursor);
- void on_update_selection(int ic, const char *text);
-
- void on_set_language(unsigned int language);
-
- void on_set_imdata(char *buf, unsigned int len);
- void on_get_imdata(char **buf, unsigned int *len);
-
- void on_set_return_key_type(unsigned int type);
- void on_get_return_key_type(unsigned int *type);
-
- void on_set_return_key_disable(unsigned int disabled);
- void on_get_return_key_disable(unsigned int *disabled);
-
- void on_set_layout(unsigned int layout);
- void on_get_layout(unsigned int *layout);
-
- void on_reset_input_context(int ic);
-
- void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret);
-
- std::queue<ISE_MESSAGE>& get_send_message_queue();
- std::queue<ISE_MESSAGE>& get_recv_message_queue();
- Ecore_Pipe* get_message_pipe();
-
- void wait_for_reply_message();
-
- void process_recved_messages();
- bool process_recved_messages_until_reply_found(std::string command, std::vector<std::string> &values);
- void handle_recved_message(ISE_MESSAGE &message);
-
- static CWebHelperAgentWebSocket* get_current_instance();
-protected:
- static CWebHelperAgentWebSocket *m_current_instance;
-
- std::queue<ISE_MESSAGE> m_send_message_queue;
- std::queue<ISE_MESSAGE> m_recv_message_queue;
-
- Ecore_Pipe *m_message_pipe;
-
- bool m_initialized;
-};
-
-#endif // _WEB_HELPER_AGENT_WEBSOCKET_H_
#include <dlog.h>
#ifdef WEBSOCKET
-#include "legacy_support/websocket.h"
+#include "websocket.h"
extern CWebHelperAgentWebSocket g_websocket;
#endif
#include <Ecore.h>
#ifdef WEBSOCKET
-#include "legacy_support/websocket.h"
+#include "websocket.h"
#endif
//SCL_BEGIN_DECLS
--- /dev/null
+/*
+ * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <dlog.h>
+
+#include "web_helper_agent.h"
+
+#include "websocket.h"
+#include "sclcoreimpl.h"
+
+using namespace scl;
+
+typedef struct {
+ int major_version;
+ WEB_HELPER_AGENT_TYPE agent_type;
+} WEB_HELPER_AGENT_TYPES_FOR_VERSIONS;
+
+static WEB_HELPER_AGENT_TYPES_FOR_VERSIONS web_helper_agent_types_for_versions[] = {
+ {1, WEB_HELPER_AGENT_WEBSOCKET}, /* Major version 1 indicates that it uses websocket for communication */
+};
+
+static int WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM = \
+ sizeof(web_helper_agent_types_for_versions) / sizeof(WEB_HELPER_AGENT_TYPES_FOR_VERSIONS);
+
+WEB_HELPER_AGENT_TYPE CWebHelperAgent::get_web_helper_agent_type_from_major_version(int version)
+{
+ for (int loop = 0;loop < WEB_HELPER_AGENT_TYPES_FOR_VERSIONS_NUM;loop++) {
+ if (web_helper_agent_types_for_versions[loop].major_version == version) {
+ return web_helper_agent_types_for_versions[loop].agent_type;
+ }
+ }
+ return WEB_HELPER_AGENT_UNKNOWN;
+}
+
+CWebHelperAgent* CWebHelperAgent::create_web_helper_agent(WEB_HELPER_AGENT_TYPE type)
+{
+ CWebHelperAgent *ret = NULL;
+ if (type == WEB_HELPER_AGENT_WEBSOCKET) {
+ ret = new CWebHelperAgentWebSocket;
+ }
+ return ret;
+}
+
+void CWebHelperAgent::destroy_web_helper_agent(CWebHelperAgent* agent)
+{
+ if (agent) delete agent;
+}
+
+CWebHelperAgent::CWebHelperAgent()
+{
+}
+
+CWebHelperAgent::~CWebHelperAgent()
+{
+}
+
+bool CWebHelperAgent::init()
+{
+ return true;
+}
+
+bool CWebHelperAgent::exit()
+{
+ return true;
+}
+
+void CWebHelperAgent::signal(int sig)
+{
+}
+
+void CWebHelperAgent::log(const char *str)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ //impl->logise_log(str);
+ }
+}
+
+void CWebHelperAgent::commit_string(const char *str)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->commit_string(-1, "", str);
+ }
+}
+
+void CWebHelperAgent::update_preedit_string(const char *str)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->update_preedit_string(-1, "", str);
+ }
+}
+
+void CWebHelperAgent::send_key_event(unsigned int key, unsigned int key_mask)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->send_key_event(-1, "", key, key_mask);
+ }
+}
+
+void CWebHelperAgent::forward_key_event(unsigned int key)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->forward_key_event(-1, "", key, scim::SCIM_KEY_NullMask);
+ }
+}
+
+void CWebHelperAgent::set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ SclSize portrait, landscape;
+ portrait.width = portrait_width;
+ portrait.height = portrait_height;
+ landscape.width = landscape_width;
+ landscape.height = landscape_height;
+ impl->set_keyboard_size_hints(portrait, landscape);
+ }
+}
+
+void CWebHelperAgent::set_selection(int start_index, int end_index)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->set_selection(start_index, end_index);
+ }
+}
+
+void CWebHelperAgent::get_selection()
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ //impl->get_selection(-1, "", );
+ }
+}
+
+void CWebHelperAgent::get_surrounding_text(int maxlen_before, int maxlen_after)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->get_surrounding_text("", maxlen_before, maxlen_after);
+ }
+}
+
+void CWebHelperAgent::delete_surrounding_text(int offset, int len)
+{
+ CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
+ if (impl) {
+ impl->delete_surrounding_text(offset, len);
+ }
+}
+
+std::string CMagicKeyManager::get_magic_key()
+{
+ static std::string current_magic_key;
+
+ /* If we don't have magic key generated yet */
+ if (current_magic_key.length() != MAGIC_KEY_LENGTH) {
+ char magic_key[MAGIC_KEY_LENGTH + 1];
+ /* We are going to generate a magic key that contains ascii characters in the range of '0' to 'z' */
+ const char magic_key_range_lower = '0';
+ const char magic_key_range_upper = 'Z';
+
+ unsigned int seed = time(NULL);
+ for (int loop = 0;loop < MAGIC_KEY_LENGTH;loop++) {
+ magic_key[loop] = (rand_r(&seed) % (magic_key_range_upper - magic_key_range_lower)) + magic_key_range_lower;
+ }
+ magic_key[MAGIC_KEY_LENGTH] = '\0';
+
+ current_magic_key = magic_key;
+ }
+
+ return current_magic_key;
+}
--- /dev/null
+/*
+ * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _WEB_HELPER_AGENT_H_
+#define _WEB_HELPER_AGENT_H_
+
+#define MAGIC_KEY_LENGTH 32
+#define VERSION_DELIMITER '.'
+#define VERSION_TOKEN_NUM 2 // We are expecting 2 version tokens : MAJOR and MINOR
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+class CStringTokenizer
+{
+public:
+ static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
+ unsigned int loop = 0;
+ unsigned int start = 0;
+ for (loop = 0;loop < s.length();loop++) {
+ if (s.at(loop) == delim) {
+ std::string item = s.substr(start, loop - start);
+ elems.push_back(item);
+ start = loop + 1;
+ }
+ }
+ std::string item = s.substr(start, loop - start);
+ elems.push_back(item);
+ return elems;
+ }
+
+ static std::vector<std::string> split(const std::string &s, char delim) {
+ std::vector<std::string> elems;
+ split(s, delim, elems);
+ return elems;
+ }
+};
+
+typedef enum {
+ WEB_HELPER_AGENT_UNKNOWN,
+ WEB_HELPER_AGENT_WEBSOCKET,
+ WEB_HELPER_AGENT_DIRECT,
+} WEB_HELPER_AGENT_TYPE;
+
+class CMagicKeyManager
+{
+public:
+ static std::string get_magic_key();
+};
+
+class CWebHelperAgent
+{
+public:
+ CWebHelperAgent();
+ virtual ~CWebHelperAgent();
+
+ virtual bool init();
+ virtual bool exit();
+
+ virtual bool run() { return false; }
+ virtual void signal(int sig);
+
+ virtual void on_init() {}
+ virtual void on_exit() {}
+
+ virtual void on_focus_in(int ic) {}
+ virtual void on_focus_out(int ic) {}
+
+ virtual void on_show(int ic) {}
+ virtual void on_hide(int ic) {}
+
+ virtual void on_set_rotation(int degree) {}
+
+ virtual void on_update_cursor_position(int ic, int cursor_pos) {}
+ virtual void on_update_surrounding_text(int ic, const char *text, int cursor) {}
+ virtual void on_update_selection(int ic, const char *text) {}
+
+ virtual void on_set_language(unsigned int language) {}
+
+ virtual void on_set_imdata(char *buf, unsigned int len) {}
+ virtual void on_get_imdata(char **buf, unsigned int *len) {}
+
+ virtual void on_set_return_key_type(unsigned int type) {}
+ virtual void on_get_return_key_type(unsigned int *type) {}
+
+ virtual void on_set_return_key_disable(unsigned int disabled) {}
+ virtual void on_get_return_key_disable(unsigned int *disabled) {}
+
+ virtual void on_set_layout(unsigned int layout) {}
+ virtual void on_get_layout(unsigned int *layout) {}
+
+ virtual void on_reset_input_context(int ic) {}
+
+ virtual void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret) {}
+
+
+ virtual void log(const char *str);
+ virtual void commit_string(const char *str);
+ virtual void update_preedit_string(const char *str);
+ virtual void send_key_event(unsigned int key, unsigned int key_mask);
+ virtual void forward_key_event(unsigned int key);
+ virtual void set_keyboard_sizes(int portrait_width, int portrait_height, int landscape_width, int landscape_height);
+ virtual void set_selection(int start_index, int end_index);
+ virtual void get_selection();
+ virtual void get_surrounding_text(int maxlen_before, int maxlen_after);
+ virtual void delete_surrounding_text(int offset, int len);
+
+public:
+ static WEB_HELPER_AGENT_TYPE get_web_helper_agent_type_from_major_version(int version);
+ static CWebHelperAgent* create_web_helper_agent(WEB_HELPER_AGENT_TYPE type);
+ static void destroy_web_helper_agent(CWebHelperAgent* agent);
+};
+
+#endif // _WEB_HELPER_AGENT_H_
--- /dev/null
+/*
+ * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <Ecore.h>
+#include <Ecore_IMF.h>
+#include <dlog.h>
+
+#include "websocket.h"
+
+#include <syslog.h>
+#include <signal.h>
+
+#include <libwebsockets.h>
+
+#ifdef WAYLAND
+#define EFL_BETA_API_SUPPORT
+#include <Ecore_Wl2.h>
+#endif
+
+#define WEBSOCKET_PORT 7681
+
+#define RECVED_MESSAGE "recved"
+#define MESSAGE_LEFT "left"
+
+pthread_t g_ws_server_thread = (pthread_t)NULL;
+pthread_mutex_t g_ws_server_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+pthread_cond_t g_ws_query_condition = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t g_ws_query_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+bool g_ws_server_exit = false;
+struct lws_context *g_ws_server_context = NULL;
+
+CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::m_current_instance = NULL;
+
+int force_exit = 0;
+
+enum protocols {
+ /* always first */
+ PROTOCOL_HTTP = 0,
+
+ PROTOCOL_KEYBOARD,
+
+ /* always last */
+ MAX_PROTOCOL_COUNT
+};
+
+struct per_session_data__http {
+ int fd;
+};
+
+static int callback_http(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ return 0;
+}
+
+struct per_session_data__keyboard {
+ int session_id;
+ int valid;
+ int need_init;
+ int initialized;
+};
+
+static int callback_keyboard(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len);
+
+static struct lws_protocols protocols[] = {
+ {
+ "http-only",
+ callback_http,
+ sizeof(struct per_session_data__http),
+ 0,
+ },
+ {
+ "keyboard-protocol",
+ callback_keyboard,
+ sizeof(struct per_session_data__keyboard),
+ 32,
+ },
+ { NULL, NULL, 0, 0 }
+};
+
+
+static int callback_client(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ switch (reason) {
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ LOGD("[ClientTest] Connection established");
+ break;
+
+ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
+ LOGD("[ClientTest] Connection error");
+ break;
+
+ case LWS_CALLBACK_CLOSED:
+ LOGD("[ClientTest] Connection closed");
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int test_client_connection(void)
+{
+ struct lws_context *context = NULL;
+ struct lws_context_creation_info context_info;
+ struct lws_client_connect_info connect_info;
+ struct lws *wsi = NULL;
+
+ memset(&context_info, 0, sizeof context_info);
+ memset(&connect_info, 0, sizeof(connect_info));
+
+ const int protocols_num = sizeof(protocols) / sizeof(lws_protocols);
+ static struct lws_protocols client_protocols[protocols_num];
+
+ memcpy(&client_protocols, protocols, sizeof(protocols));
+ for (int loop = 0; loop < protocols_num - 1; loop++) {
+ client_protocols[loop].callback = callback_client;
+ }
+
+ context_info.port = CONTEXT_PORT_NO_LISTEN;
+ context_info.protocols = protocols;
+ context_info.gid = -1;
+ context_info.uid = -1;
+
+ context = lws_create_context(&context_info);
+ LOGD("[ClientTest] create_context : %p", context);
+ if (context == NULL) {
+ return -1;
+ }
+
+ connect_info.address = "localhost";
+ connect_info.port = WEBSOCKET_PORT;
+ connect_info.path = "/";
+ connect_info.context = context;
+ connect_info.ssl_connection = 0;
+ connect_info.host = connect_info.address;
+ connect_info.origin = connect_info.address;
+ connect_info.ietf_version_or_minus_one = -1;
+ connect_info.protocol = "keyboard-protocol";
+
+ wsi = lws_client_connect_via_info(&connect_info);
+ LOGD("[ClientTest] wsi created : %p", wsi);
+
+ if (wsi) {
+ lws_service(context, 50);
+ }
+
+ lws_context_destroy(context);
+
+ return 0;
+}
+
+static Ecore_Timer *g_flush_server_recv_buffer_timer = NULL;
+static std::string server_recv_buffer;
+static Eina_Bool flush_server_recv_buffer_func(void *user)
+{
+ LOGD("flushing recv buffer");
+ CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
+ struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user;
+
+ if (g_flush_server_recv_buffer_timer)
+ ecore_timer_del(g_flush_server_recv_buffer_timer);
+ g_flush_server_recv_buffer_timer = NULL;
+
+ if (!agent || !pss) return ECORE_CALLBACK_CANCEL;
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ ISE_MESSAGE message = CISEMessageSerializer::deserialize(server_recv_buffer);
+ server_recv_buffer.clear();
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
+ /*
+ if (message.values.at(0).compare(CMagicKeyManager::get_magic_key()) == 0) {
+ LOGD("LOGIN successful, validating client");
+ pss->valid = true;
+ } else {
+ LOGD("LOGIN failed, invalidating client");
+ pss->valid = false;
+ }
+ */
+ pss->valid = true;
+
+ if (agent->initialized()) {
+ pss->need_init = true;
+ ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
+ }
+ }
+
+ /* Ignore valid check since the magic key is not used anymore */
+ if (!pss->valid) pss->valid = true;
+
+ if (pss->valid) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ std::queue<ISE_MESSAGE>& messages = agent->get_recv_message_queue();
+ messages.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ ecore_pipe_write(agent->get_message_pipe(), RECVED_MESSAGE, strlen(RECVED_MESSAGE));
+
+ /* If we received reply message, let's send signal to wake up our main thread */
+ if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
+ pthread_mutex_lock(&g_ws_query_mutex);
+ pthread_cond_signal(&g_ws_query_condition);
+ pthread_mutex_unlock(&g_ws_query_mutex);
+ }
+ } else {
+ LOGD("Ignoring data received since client is not valid %d", pss->session_id);
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static int callback_keyboard(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ static int last_session_id = 0;
+ const int bufsize = 512;
+ int n = 0;
+ unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + bufsize +
+ LWS_SEND_BUFFER_POST_PADDING];
+ unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
+ struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user;
+ CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
+
+ switch (reason) {
+ case LWS_CALLBACK_ESTABLISHED:
+ pss->session_id = ++last_session_id;
+ LOGD("LWS_CALLBACK_ESTABLISHED : %p %d", g_ws_server_context, pss->session_id);
+ pss->valid = false;
+ pss->need_init = false;
+ pss->initialized = false;
+ if (g_ws_server_context) {
+ ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
+ }
+ break;
+
+ case LWS_CALLBACK_CLOSED:
+ LOGD("LWS_CALLBACK_CLOSED : %d", pss->session_id);
+ break;
+
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ if (agent) {
+ /* Ignore valid check since the magic key is not used anymore */
+ if (!pss->valid) pss->valid = true;
+
+ /* We allow data tranmission only if this client is guaranteed to be valid */
+ if (pss->valid) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ std::queue<ISE_MESSAGE>& messages = agent->get_send_message_queue();
+
+ if (pss->need_init && !pss->initialized) {
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT];
+ std::string str = CISEMessageSerializer::serialize(message);
+ SECURE_LOGD("SEND_WEBSOCKET_MESSAGE : %d %s", pss->session_id, str.c_str());
+ n = snprintf((char *)p, bufsize, "%s", str.c_str());
+ /* too small for partial */
+ n = lws_write(wsi, p, n, LWS_WRITE_TEXT);
+ pss->need_init = false;
+ pss->initialized = true;
+ } else {
+ /* One write allowed per one writable callback */
+ if (messages.size() > 0) {
+ ISE_MESSAGE &message = messages.front();
+ bool drop = false;
+ if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT]) == 0) {
+ if (pss->initialized) {
+ drop = true;
+ } else {
+ pss->initialized = true;
+ }
+ }
+ if (!drop) {
+ std::string str = CISEMessageSerializer::serialize(message);
+ SECURE_LOGD("SEND_WEBSOCKET_MESSAGE : %d %s", pss->session_id, str.c_str());
+ n = snprintf((char *)p, bufsize, "%s", str.c_str());
+ /* too small for partial */
+ n = lws_write(wsi, p, n, LWS_WRITE_TEXT);
+ }
+ messages.pop();
+ }
+ }
+ if (messages.size() > 0) {
+ ecore_pipe_write(agent->get_message_pipe(), MESSAGE_LEFT, strlen(MESSAGE_LEFT));
+ }
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (n < 0) {
+ LOGE("ERROR %d writing to di socket %d", n, pss->session_id);
+ }
+
+ if (messages.size() > 0) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ }
+ } else {
+ LOGD("Rejecting data transmission since client is not valid : %d", pss->session_id);
+ }
+ }
+ break;
+
+ case LWS_CALLBACK_RECEIVE:
+ if (in) {
+ if (g_flush_server_recv_buffer_timer) {
+ ecore_thread_main_loop_begin();
+ ecore_timer_del(g_flush_server_recv_buffer_timer);
+ g_flush_server_recv_buffer_timer = NULL;
+ ecore_thread_main_loop_end();
+ }
+
+ std::string str = std::string((const char *)in, len);
+ if (CISEMessageSerializer::valid(str)) {
+ LOGD("A valid new message received, flush previous buffer");
+ flush_server_recv_buffer_func((void*)pss);
+ }
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ server_recv_buffer += str;
+ SECURE_LOGD("RECEIVE callback : [%zu] [%s], [%s]", len, str.c_str(), server_recv_buffer.c_str());
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ ecore_thread_main_loop_begin();
+ g_flush_server_recv_buffer_timer = ecore_timer_add(0.05, flush_server_recv_buffer_func, (void*)pss);
+ SECURE_LOGD("flush timer registered : %p", g_flush_server_recv_buffer_timer);
+ ecore_thread_main_loop_end();
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void *process_ws_server(void *data)
+{
+ while (!force_exit && !g_ws_server_exit) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ if (g_ws_server_context) {
+ lws_service(g_ws_server_context, 50);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+ LOGD("process_ws_server exits now");
+ return NULL;
+}
+
+void log_func(int level, const char *line)
+{
+ if (line) {
+ LOGD("LEVEL : %d , %s", level, line);
+ }
+}
+
+CWebHelperAgentWebSocket::CWebHelperAgentWebSocket()
+{
+ if (m_current_instance != NULL) {
+ LOGD("WARNING : m_current_instance is NOT NULL");
+ }
+ m_current_instance = this;
+ m_message_pipe = NULL;
+ m_initialized = false;
+}
+
+CWebHelperAgentWebSocket::~CWebHelperAgentWebSocket()
+{
+ if (m_current_instance == this) {
+ m_current_instance = NULL;
+ }
+
+ if (m_message_pipe) {
+ ecore_pipe_del(m_message_pipe);
+ m_message_pipe = NULL;
+ }
+}
+
+static void message_pipe_handler(void *data, void *buffer, unsigned int nbyte)
+{
+ if (buffer) {
+ if (strncmp((const char*)buffer, RECVED_MESSAGE, strlen(RECVED_MESSAGE)) == 0) {
+ CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
+ if (agent) {
+ agent->process_recved_messages();
+ }
+ } else {
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+ }
+}
+
+bool CWebHelperAgentWebSocket::init()
+{
+ bool ret = true;
+
+ struct lws_context_creation_info info;
+
+ memset(&info, 0, sizeof info);
+ info.port = WEBSOCKET_PORT;
+
+ int log_level = LLL_ERR | LLL_WARN | LLL_DEBUG;
+ lws_set_log_level(log_level, log_func);
+
+ info.iface = NULL;
+ info.protocols = protocols;
+ info.extensions = NULL;
+ info.ssl_cert_filepath = NULL;
+ info.ssl_private_key_filepath = NULL;
+ info.gid = -1;
+ info.uid = -1;
+ info.options = 0;
+
+ ecore_init();
+
+ /* The WebSocket server is running on a separate thread, and let the thread send a message
+ through this pipe to guarantee thread safety */
+ m_message_pipe = ecore_pipe_add(message_pipe_handler, NULL);
+
+ /* Let's retry creating server context for a certain number of times */
+ const int max_retry_num = 30;
+ int retry_num = 0;
+
+ do {
+ g_ws_server_context = lws_create_context(&info);
+ LOGD("libwebsocket context : %p", g_ws_server_context);
+ usleep(100 * 1000);
+ } while (g_ws_server_context == NULL && retry_num++ < max_retry_num);
+
+ pthread_mutex_init(&g_ws_server_mutex, NULL);
+
+ pthread_mutex_init(&g_ws_query_mutex, NULL);
+ pthread_cond_init(&g_ws_query_condition, NULL);
+
+ m_initialized = true;
+
+ return ret;
+}
+
+bool CWebHelperAgentWebSocket::exit()
+{
+ if (g_flush_server_recv_buffer_timer)
+ ecore_timer_del(g_flush_server_recv_buffer_timer);
+ g_flush_server_recv_buffer_timer = NULL;
+
+ on_exit();
+
+ g_ws_server_exit = true;
+ if (g_ws_server_context) {
+ lws_cancel_service(g_ws_server_context);
+ }
+
+ if (m_message_pipe) {
+ ecore_pipe_del(m_message_pipe);
+ m_message_pipe = NULL;
+ }
+
+ if (g_ws_server_thread) {
+ pthread_join(g_ws_server_thread, NULL);
+ }
+
+ pthread_cond_destroy(&g_ws_query_condition);
+ pthread_mutex_destroy(&g_ws_query_mutex);
+
+ pthread_mutex_destroy(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_context_destroy(g_ws_server_context);
+ g_ws_server_context = NULL;
+ }
+
+ ecore_shutdown();
+
+ return true;
+}
+
+bool CWebHelperAgentWebSocket::run()
+{
+ if (!m_initialized) {
+ LOGE("Not initialized");
+ return false;
+ }
+
+ bool ret = false;
+ if (g_ws_server_context) {
+ if (pthread_create(&g_ws_server_thread, NULL, &process_ws_server, NULL) != 0) {
+ g_ws_server_thread = (pthread_t)NULL;
+ ret = false;
+
+ on_init();
+
+ test_client_connection();
+ }
+ } else {
+ LOGE("Failed creating server context : %p", g_ws_server_context);
+ ret = false;
+ }
+ return ret;
+}
+
+void CWebHelperAgentWebSocket::signal(int sig)
+{
+ force_exit = 1;
+}
+
+template<class T>
+std::string to_string(T i)
+{
+ std::stringstream ss;
+ std::string s;
+ ss << i;
+ s = ss.str();
+
+ return s;
+}
+
+void CWebHelperAgentWebSocket::on_init()
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_exit()
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_EXIT];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_focus_in(int ic)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_IN];
+ message.values.push_back(to_string(ic));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_focus_out(int ic)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_OUT];
+ message.values.push_back(to_string(ic));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_show(int ic)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SHOW];
+ message.values.push_back(to_string(ic));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ LOGD("put into send message buffer");
+}
+
+void CWebHelperAgentWebSocket::on_hide(int ic)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_HIDE];
+ message.values.push_back(to_string(ic));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_set_rotation(int degree)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_ROTATION];
+ message.values.push_back(to_string(degree));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_update_cursor_position(int ic, int cursor_pos)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION];
+ message.values.push_back(to_string(ic));
+ message.values.push_back(to_string(cursor_pos));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_update_surrounding_text(int ic, const char *text, int cursor)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT];
+ message.values.push_back(to_string(cursor));
+ message.values.push_back(text);
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_update_selection(int ic, const char *text)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SELECTION];
+ message.values.push_back(text);
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_set_language(unsigned int language)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LANGUAGE];
+
+ bool found = false;
+ for (unsigned int loop = 0;loop < sizeof(ISE_LANGUAGE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (language == (unsigned int)ISE_LANGUAGE_TYPES[loop].type_value) {
+ message.values.push_back(ISE_LANGUAGE_TYPES[loop].type_string);
+ found = true;
+ }
+ }
+
+ if (found) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+}
+
+void CWebHelperAgentWebSocket::on_set_imdata(char *buf, unsigned int len)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_IMDATA];
+ message.values.push_back(buf);
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_get_imdata(char **buf, unsigned int *len)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ wait_for_reply_message();
+
+ std::vector<std::string> values;
+ /* Check if we received reply for GET_IMDATA message */
+ if (process_recved_messages_until_reply_found(
+ ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA], values)) {
+ if (values.size() > 0 && buf && len) {
+ int string_length = values.at(0).length();
+ (*buf) = new char[string_length + 1];
+ if (*buf) {
+ strncpy(*buf, values.at(0).c_str(), string_length);
+ /* Make sure this is a null-terminated string */
+ *(*buf + string_length) = '\0';
+ *len = string_length;
+ }
+ }
+ } else {
+ LOGD("process_recved_messages_until_reply_found returned FALSE");
+ }
+ /* Now process the rest in the recv buffer */
+ process_recved_messages();
+}
+
+void CWebHelperAgentWebSocket::on_set_return_key_type(unsigned int type)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE];
+
+ bool found = false;
+ for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (type == (unsigned int)ISE_RETURN_KEY_TYPES[loop].type_value) {
+ message.values.push_back(ISE_RETURN_KEY_TYPES[loop].type_string);
+ found = true;
+ }
+ }
+
+ if (found) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+}
+
+void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ wait_for_reply_message();
+
+ std::vector<std::string> values;
+ /* Check if we received reply for GET_RETURN_KEY_TYPE message */
+ if (process_recved_messages_until_reply_found(
+ ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE], values)) {
+ if (type) {
+ for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (values.at(0).compare(ISE_RETURN_KEY_TYPES[loop].type_string) == 0) {
+ *type = ISE_RETURN_KEY_TYPES[loop].type_value;
+ }
+ }
+ }
+ }
+ /* Now process the rest in the recv buffer */
+ process_recved_messages();
+}
+
+void CWebHelperAgentWebSocket::on_set_return_key_disable(unsigned int disabled)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE];
+
+ bool found = false;
+ for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (disabled == (unsigned int)ISE_TRUEFALSE_TYPES[loop].type_value) {
+ message.values.push_back(ISE_TRUEFALSE_TYPES[loop].type_string);
+ found = true;
+ }
+ }
+
+ if (found) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+}
+
+void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ wait_for_reply_message();
+
+ std::vector<std::string> values;
+ /* Check if we received reply for GET_RETURN_KEY_DISABLE message */
+ if (process_recved_messages_until_reply_found(
+ ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE], values)) {
+ if (disabled) {
+ for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
+ *disabled = ISE_TRUEFALSE_TYPES[loop].type_value;
+ }
+ }
+ }
+ }
+ /* Now process the rest in the recv buffer */
+ process_recved_messages();
+}
+
+void CWebHelperAgentWebSocket::on_set_layout(unsigned int layout)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LAYOUT];
+
+ bool found = false;
+ for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (layout == (unsigned int)ISE_LAYOUT_TYPES[loop].type_value) {
+ message.values.push_back(ISE_LAYOUT_TYPES[loop].type_string);
+ found = true;
+ }
+ }
+
+ if (found) {
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+}
+
+void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT];
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ wait_for_reply_message();
+
+ std::vector<std::string> values;
+ /* Check if we received reply for GET_LAYOUT message */
+ if (process_recved_messages_until_reply_found(
+ ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT], values)) {
+ if (layout) {
+ for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (values.at(0).compare(ISE_LAYOUT_TYPES[loop].type_string) == 0) {
+ *layout = ISE_LAYOUT_TYPES[loop].type_value;
+ }
+ }
+ }
+ }
+ /* Now process the rest in the recv buffer */
+ process_recved_messages();
+}
+
+void CWebHelperAgentWebSocket::on_reset_input_context(int ic)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT];
+ message.values.push_back(to_string(ic));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+}
+
+void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret)
+{
+ ISE_MESSAGE message;
+ message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
+ message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT];
+ message.values.push_back(to_string(code));
+ message.values.push_back(to_string(mask));
+ message.values.push_back(to_string(layout));
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+ m_send_message_queue.push(message);
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+
+ wait_for_reply_message();
+
+ std::vector<std::string> values;
+ /* Check if we received reply for PROCESS_KEY_EVENT message */
+ if (process_recved_messages_until_reply_found(
+ ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT], values)) {
+ if (ret) {
+ for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
+ if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
+ *ret = ISE_TRUEFALSE_TYPES[loop].type_value;
+ }
+ }
+ }
+ }
+ /* Now process the rest in the recv buffer */
+ process_recved_messages();
+}
+
+CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::get_current_instance()
+{
+ return m_current_instance;
+}
+
+std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_send_message_queue()
+{
+ return m_send_message_queue;
+}
+
+std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_recv_message_queue()
+{
+ return m_recv_message_queue;
+}
+
+Ecore_Pipe* CWebHelperAgentWebSocket::get_message_pipe()
+{
+ return m_message_pipe;
+}
+
+void CWebHelperAgentWebSocket::wait_for_reply_message()
+{
+ /* Let's wait for at most REPLY_TIMEOUT */
+ struct timeval now;
+ struct timespec timeout;
+ gettimeofday(&now, NULL);
+ timeout.tv_sec = now.tv_sec + REPLY_TIMEOUT.tv_sec;
+ timeout.tv_nsec = (now.tv_usec + REPLY_TIMEOUT.tv_usec) * 1000;
+ pthread_mutex_lock(&g_ws_query_mutex);
+ pthread_cond_timedwait(&g_ws_query_condition, &g_ws_query_mutex, &timeout);
+ pthread_mutex_unlock(&g_ws_query_mutex);
+}
+
+void CWebHelperAgentWebSocket::process_recved_messages()
+{
+ pthread_mutex_lock(&g_ws_server_mutex);
+
+ while (m_recv_message_queue.size() > 0) {
+ ISE_MESSAGE &message = m_recv_message_queue.front();
+
+ handle_recved_message(message);
+
+ m_recv_message_queue.pop();
+ }
+
+ pthread_mutex_unlock(&g_ws_server_mutex);
+}
+
+bool CWebHelperAgentWebSocket::process_recved_messages_until_reply_found(std::string command, std::vector<std::string> &values)
+{
+ bool ret = false;
+
+ pthread_mutex_lock(&g_ws_server_mutex);
+
+ while (ret == false && m_recv_message_queue.size() > 0) {
+ ISE_MESSAGE &message = m_recv_message_queue.front();
+
+ if (message.command.compare(command) == 0 &&
+ message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
+ ret = true;
+ values = message.values;
+ }
+ handle_recved_message(message);
+
+ m_recv_message_queue.pop();
+ }
+
+ pthread_mutex_unlock(&g_ws_server_mutex);
+
+ return ret;
+}
+
+void CWebHelperAgentWebSocket::handle_recved_message(ISE_MESSAGE &message)
+{
+ static bool _key_event_processing = false;
+ if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOG]) == 0) {
+ std::string str = "";
+ for (unsigned int loop = 0;loop < message.values.size();loop++) {
+ str += message.values.at(loop).c_str();
+ if (loop < message.values.size() - 1) {
+ str += " ";
+ }
+ }
+ log(str.c_str());
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_COMMIT_STRING]) == 0) {
+ std::string str = "";
+ for (unsigned int loop = 0;loop < message.values.size();loop++) {
+ str += message.values.at(loop).c_str();
+ if (loop < message.values.size() - 1) {
+ str += " ";
+ }
+ }
+ if (_key_event_processing) {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ select(0, NULL, NULL, NULL, &tv);
+ _key_event_processing = false;
+ }
+ commit_string(str.c_str());
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING]) == 0) {
+ std::string str = "";
+ for (unsigned int loop = 0;loop < message.values.size();loop++) {
+ str += message.values.at(loop).c_str();
+ if (loop < message.values.size() - 1) {
+ str += " ";
+ }
+ }
+ update_preedit_string(str.c_str());
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SEND_KEY_EVENT]) == 0) {
+ if (message.values.size() == 1) {
+ forward_key_event(atoi(message.values.at(0).c_str()));
+ _key_event_processing = true;
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES]) == 0) {
+ LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES");
+ int portrait_width, portrait_height;
+ int landscape_width, landscape_height;
+
+ if (message.values.size() == 4 || message.values.size() == 2) {
+ portrait_width = atoi(message.values.at(0).c_str());
+ portrait_height = atoi(message.values.at(1).c_str());
+ if (message.values.size() == 2) {
+ landscape_width = portrait_width;
+ landscape_height = portrait_height;
+ } else {
+ landscape_width = atoi(message.values.at(2).c_str());
+ landscape_height = atoi(message.values.at(3).c_str());
+ }
+
+ LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES : %d %d %d %d",
+ portrait_width, portrait_height, landscape_width, landscape_height);
+
+#ifdef WAYLAND
+ /* Since the full screen IME makes the client application fully obscured,
+ * when it hides the client receives resume command and try to show IME again.
+ * So here we are adjusting the height value when the requested keyboard size
+ * is the same with the screen size, as a workaround */
+ int scr_w = 0, scr_h = 0;
+ ecore_wl2_sync();
+ Ecore_Wl2_Display *ewd = NULL;
+ if ((ewd = ecore_wl2_connected_display_get(NULL))) {
+ ecore_wl2_display_screen_size_get(ewd, &scr_w, &scr_h);
+
+ if (scr_w == portrait_width && scr_h == portrait_height) {
+ portrait_height -= 1;
+ }
+ if (scr_h == landscape_width && scr_w == landscape_height) {
+ landscape_height -= 1;
+ }
+ }
+#endif
+
+ set_keyboard_sizes(
+ portrait_width, portrait_height, landscape_width, landscape_height);
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_SELECTION]) == 0) {
+ LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION");
+ if (message.values.size() == 2) {
+ LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION : %d %d",
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ set_selection(
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SELECTION]) == 0) {
+ if (message.values.size() == 0) {
+ get_selection();
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT]) == 0) {
+ LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT");
+ if (message.values.size() == 2) {
+ LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT : %d %d",
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ get_surrounding_text(
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT]) == 0) {
+ LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT");
+ if (message.values.size() == 2) {
+ LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT : %d %d",
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ delete_surrounding_text(
+ atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
+ }
+ } else if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
+ if (g_ws_server_context) {
+ lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
+ } else {
+ LOGD("WARNING : g_ws_server_context is NULL");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _WEB_HELPER_AGENT_WEBSOCKET_H_
+#define _WEB_HELPER_AGENT_WEBSOCKET_H_
+
+#include "web_helper_agent.h"
+
+#include <queue>
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <Ecore_IMF.h>
+
+/* Wait for at most 1 second */
+const struct timeval REPLY_TIMEOUT = {1, 0};
+
+typedef enum {
+ ISE_MESSAGE_TYPE_PLAIN,
+ ISE_MESSAGE_TYPE_QUERY,
+ ISE_MESSAGE_TYPE_REPLY,
+
+ ISE_MESSAGE_TYPES_NUM,
+} ISE_MESSAGE_TYPES;
+
+const std::string ISE_MESSAGE_TYPE_STRINGS[] = {
+ "plain", // ISE_MESSAGE_TYPE_PLAIN,
+ "query", // ISE_MESSAGE_TYPE_QUERY
+ "reply", // ISE_MESSAGE_TYPE_REPLY
+};
+
+typedef enum {
+ ISE_MESSAGE_COMMAND_INIT,
+ ISE_MESSAGE_COMMAND_EXIT,
+
+ ISE_MESSAGE_COMMAND_FOCUS_IN,
+ ISE_MESSAGE_COMMAND_FOCUS_OUT,
+ ISE_MESSAGE_COMMAND_SHOW,
+ ISE_MESSAGE_COMMAND_HIDE,
+ ISE_MESSAGE_COMMAND_SET_ROTATION,
+ ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION,
+ ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT,
+ ISE_MESSAGE_COMMAND_UPDATE_SELECTION,
+ ISE_MESSAGE_COMMAND_SET_LANGUAGE,
+ ISE_MESSAGE_COMMAND_SET_IMDATA,
+ ISE_MESSAGE_COMMAND_GET_IMDATA,
+ ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE,
+ ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE,
+ ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE,
+ ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE,
+ ISE_MESSAGE_COMMAND_SET_LAYOUT,
+ ISE_MESSAGE_COMMAND_GET_LAYOUT,
+ ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT,
+ ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT,
+
+ ISE_MESSAGE_COMMAND_LOG,
+ ISE_MESSAGE_COMMAND_COMMIT_STRING,
+ ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING,
+ ISE_MESSAGE_COMMAND_SEND_KEY_EVENT,
+ ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT,
+ ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES,
+ ISE_MESSAGE_COMMAND_SET_SELECTION,
+ ISE_MESSAGE_COMMAND_GET_SELECTION,
+ ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT,
+ ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT,
+ ISE_MESSAGE_COMMAND_LOGIN,
+
+ ISE_MESSAGE_COMMANDS_NUM,
+} ISE_MESSAGE_COMMANDS;
+
+const std::string ISE_MESSAGE_COMMAND_STRINGS[] = {
+ "init", // ISE_MESSAGE_COMMAND_INIT,
+ "exit", // ISE_MESSAGE_COMMAND_EXIT,
+
+ "focus_in", // ISE_MESSAGE_COMMAND_FOCUS_IN,
+ "focus_out", // ISE_MESSAGE_COMMAND_FOCUS_OUT,
+ "show", // ISE_MESSAGE_COMMAND_SHOW,
+ "hide", // ISE_MESSAGE_COMMAND_HIDE,
+ "set_rotation", // ISE_MESSAGE_COMMAND_SET_ROTATION,
+ "update_cursor_position", // ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION,
+ "update_surrounding_text", // ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT,
+ "update_selection", // ISE_MESSAGE_COMMAND_UPDATE_SELECTION
+ "set_language", // ISE_MESSAGE_COMMAND_SET_LANGUAGE,
+ "set_imdata", // ISE_MESSAGE_COMMAND_SET_IMDATA,
+ "get_imdata", // ISE_MESSAGE_COMMAND_GET_IMDATA,
+ "set_return_key_type", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE,
+ "get_return_key_type", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE,
+ "set_return_key_disable", // ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE,
+ "get_return_key_disable", // ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE,
+ "set_layout", // ISE_MESSAGE_COMMAND_SET_LAYOUT,
+ "get_layout", // ISE_MESSAGE_COMMAND_GET_LAYOUT,
+ "reset_input_context", // ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT,
+ "process_key_event", // ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT,
+
+ "log", // ISE_MESSAGE_COMMAND_LOG,
+ "commit_string", // ISE_MESSAGE_COMMAND_COMMIT_STRING,
+ "update_preedit_string", // ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING,
+ "send_key_event", // ISE_MESSAGE_COMMAND_SEND_KEY_EVENT,
+ "forward_key_event", // ISE_MESSAGE_COMMAND_FORWARD_KEY_EVENT,
+ "set_keyboard_sizes", // ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES,
+ "set_selection", // ISE_MESSAGE_COMMAND_SET_SELECTION,
+ "get_selection", // ISE_MESSAGE_COMMAND_GET_SELECTION,
+ "get_surrounding_text", // ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT,
+ "delete_surrounding_text", // ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT,
+ "login", // ISE_MESSAGE_COMMAND_LOGIN,
+};
+
+typedef struct {
+ std::string type;
+ std::string command;
+ std::vector<std::string> values;
+} ISE_MESSAGE;
+
+typedef struct {
+ int type_value;
+ std::string type_string;
+} ISE_TYPE_VALUE_STRING;
+
+const ISE_TYPE_VALUE_STRING ISE_RETURN_KEY_TYPES[] = {
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, "default"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE, "done"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO, "go"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, "join"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, "login"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, "next"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, "search"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND, "send"},
+ {ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN, "signin"},
+};
+
+const ISE_TYPE_VALUE_STRING ISE_LAYOUT_TYPES[] = {
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, "normal"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER, "number"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL, "email"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_URL, "url"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER, "phonenumber"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_IP, "ip"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH, "month"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY, "numberonly"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD, "password"},
+ {ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME, "datetime"},
+};
+
+const ISE_TYPE_VALUE_STRING ISE_LANGUAGE_TYPES[] = {
+ {ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC, "automatic"},
+ {ECORE_IMF_INPUT_PANEL_LANG_ALPHABET, "alphabet"},
+};
+
+/* FIXME : Should consider the case if the boolean value does not match with EINA_TRUE or EINA_FALSE */
+const ISE_TYPE_VALUE_STRING ISE_TRUEFALSE_TYPES[] = {
+ {EINA_FALSE, "false"},
+ {EINA_TRUE, "true"},
+};
+
+class CISEMessageSerializer
+{
+protected:
+ /* FIXME : Temporary solution for distinguish commands and values */
+ static const char MESSAGE_DELIMETER = ' ';
+
+public:
+ static std::string serialize(ISE_MESSAGE message) {
+ std::string ret;
+ ret += message.type;
+ ret += MESSAGE_DELIMETER;
+ ret += message.command;
+ for (unsigned int loop = 0;loop < message.values.size();loop++) {
+ ret += MESSAGE_DELIMETER;
+ ret += message.values.at(loop);
+ }
+ return ret;
+ }
+
+ static ISE_MESSAGE deserialize(std::string message) {
+ ISE_MESSAGE ret;
+ std::vector<std::string> vec = CStringTokenizer::split(message, MESSAGE_DELIMETER);
+ if (vec.size() > 1) {
+ ret.type = vec.at(0);
+ vec.erase(vec.begin());
+ ret.command = vec.at(0);
+ vec.erase(vec.begin());
+ ret.values = vec;
+ }
+ return ret;
+ }
+
+ static bool valid(std::string str)
+ {
+ int loop;
+
+ bool valid_type = false;
+ bool valid_command = false;
+
+ ISE_MESSAGE message;
+ message = deserialize(str);
+
+ for (loop = 0;!valid_type && loop < ISE_MESSAGE_TYPES_NUM;loop++) {
+ if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[loop]) == 0) {
+ valid_type = true;
+ }
+ }
+ for (loop = 0;!valid_command && loop < ISE_MESSAGE_COMMANDS_NUM;loop++) {
+ if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[loop]) == 0) {
+ valid_command = true;
+ }
+ }
+
+ return (valid_type && valid_command);
+ }
+};
+
+class CWebHelperAgentWebSocket : public CWebHelperAgent {
+public:
+ CWebHelperAgentWebSocket();
+ virtual ~CWebHelperAgentWebSocket();
+
+ bool init();
+ bool exit();
+
+ bool run();
+
+ bool initialized() { return m_initialized; }
+
+ void signal(int sig);
+
+ void on_init();
+ void on_exit();
+
+ void on_focus_in(int ic);
+ void on_focus_out(int ic);
+
+ void on_show(int ic);
+ void on_hide(int ic);
+
+ void on_set_rotation(int degree);
+
+ void on_update_cursor_position(int ic, int cursor_pos);
+ void on_update_surrounding_text(int ic, const char *text, int cursor);
+ void on_update_selection(int ic, const char *text);
+
+ void on_set_language(unsigned int language);
+
+ void on_set_imdata(char *buf, unsigned int len);
+ void on_get_imdata(char **buf, unsigned int *len);
+
+ void on_set_return_key_type(unsigned int type);
+ void on_get_return_key_type(unsigned int *type);
+
+ void on_set_return_key_disable(unsigned int disabled);
+ void on_get_return_key_disable(unsigned int *disabled);
+
+ void on_set_layout(unsigned int layout);
+ void on_get_layout(unsigned int *layout);
+
+ void on_reset_input_context(int ic);
+
+ void on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret);
+
+ std::queue<ISE_MESSAGE>& get_send_message_queue();
+ std::queue<ISE_MESSAGE>& get_recv_message_queue();
+ Ecore_Pipe* get_message_pipe();
+
+ void wait_for_reply_message();
+
+ void process_recved_messages();
+ bool process_recved_messages_until_reply_found(std::string command, std::vector<std::string> &values);
+ void handle_recved_message(ISE_MESSAGE &message);
+
+ static CWebHelperAgentWebSocket* get_current_instance();
+protected:
+ static CWebHelperAgentWebSocket *m_current_instance;
+
+ std::queue<ISE_MESSAGE> m_send_message_queue;
+ std::queue<ISE_MESSAGE> m_recv_message_queue;
+
+ Ecore_Pipe *m_message_pipe;
+
+ bool m_initialized;
+};
+
+#endif // _WEB_HELPER_AGENT_WEBSOCKET_H_