#include #include #include #include "rkt_protocol.h" #include "shm.h" #include "shmqueue.h" #include "command.h" #include "utils.h" #include #include #include "rktwebview_qt.h" static void free_data(rkt_data_t *d) { if (d->kind == version) { free(d); } else if (d->kind == event) { free(d->data.event.event); free(d); } else if (d->kind == js_result) { free(d->data.js_result.value); free(d); } else { ERROR1("UNEXPECTED: data kind %d cannot be freed\n", d->kind); } } class Handler : public QThread { public: Shm *shm; ShmQueue *command_queue; ShmQueue *result_queue; ShmQueue *event_queue; Rktwebview_qt *webview_handler; // QThread interface protected: void run(); }; static Handler *_handler; static void event_cb(rkt_data_t *data) { if (data->kind != rkt_data_kind_t::event) { return; } int wv = data->data.event.wv; char *evt = data->data.event.event; std::string evt_d(evt); _handler->event_queue->enqueue(wv, evt_d); free_data(data); } int main(int argc, char *argv[]) { const char *me = argv[0]; INFO1("%s runs\n", argv[0]); if (argc < 6) { ERROR1("%s: wrong number of arguments\n", me); exit(1); } const char *shm_name = argv[1]; const char *shm_size_str = argv[2]; const char *cmd_slot_str = argv[3]; const char *res_slot_str = argv[4]; const char *evt_slot_str = argv[5]; size_t shm_size = atoi(shm_size_str); int cmd_slot = atoi(cmd_slot_str); int res_slot = atoi(res_slot_str); int evt_slot = atoi(evt_slot_str); MKLOGSTMT(LOG_INFO, fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str)); MKLOGSTMT(LOG_INFO, fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot)); if (!(shm_size > 0 && cmd_slot > 0 && res_slot > 0 && evt_slot > 0)) { ERROR1("%s: Invalid shm size or slots\n", me); exit(2); } Handler *handler = new Handler(); _handler = handler; handler->shm = new Shm(shm_name, shm_size, false); handler->command_queue = new ShmQueue(handler->shm, cmd_slot, false); handler->result_queue = new ShmQueue(handler->shm, res_slot, false); handler->event_queue = new ShmQueue(handler->shm, evt_slot, false); handler->webview_handler = new Rktwebview_qt(argc, argv); handler->start(); handler->webview_handler->initApp(); handler->webview_handler->execApp(); INFO0("waiting for thread to end\n"); handler->wait(); INFO0("cleaning up shm\n"); delete handler->webview_handler; delete handler->command_queue; delete handler->result_queue; delete handler->event_queue; delete handler->shm; delete handler; return 0; } void Handler::run() { bool quit = false; while (!quit) { int cmd; std::string data; command_queue->dequeue(cmd, data, true); QJsonObject data_obj = QJsonDocument::fromJson(data.c_str()).object(); switch(cmd) { case CMD_QUIT: { INFO0("Got quit message\n"); webview_handler->rktQuit(); INFO0("Enqueing RESULT_QUIT to result queue\n"); result_queue->enqueue(RESULT_QUIT); quit = true; } break; case CMD_HANDLE_IS_VALID: { int wv = data_obj["wv"].toInt(); bool oke = webview_handler->rktValid(wv); result_queue->enqueue(oke); } break; case CMD_CONTEXT_NEW: { QString boilerplate_js = data_obj["boilerplate_js"].toString(); bool has_pem_cert = data_obj["has_pem_cert"].toBool(); QString pem_cert = data_obj["pem_cert"].toString(); int context = webview_handler->newContext(boilerplate_js, has_pem_cert, pem_cert); result_queue->enqueue(context); } break; case CMD_CREATE_WV: { int context = data_obj["context"].toInt(); int parent = data_obj["parent"].toInt(); int wv = webview_handler->rktWebViewCreate(context, parent, event_cb); result_queue->enqueue(wv); } break; case CMD_CLOSE_WV: { int wv = data_obj["wv"].toInt(); webview_handler->rktWebViewClose(wv); } break; case CMD_SET_URL: { int wv = data_obj["wv"].toInt(); QString url = data_obj["url"].toString(); result_t r = webview_handler->rktSetUrl(wv, url.toUtf8().constData()); result_queue->enqueue(r); } break; case CMD_SET_HTML: { int wv = data_obj["wv"].toInt(); QString html = data_obj["html"].toString(); result_t r = webview_handler->rktSetHtml(wv, html.toUtf8().constData()); result_queue->enqueue(r); } break; case CMD_RUN_JS: { int wv = data_obj["wv"].toInt(); QString js = data_obj["js"].toString(); result_t r = webview_handler->rktRunJs(wv, js); result_queue->enqueue(r); } break; case CMD_CALL_JS: { int wv = data_obj["wv"].toInt(); QString js = data_obj["js"].toString(); rkt_data_t *res = webview_handler->rktCallJs(wv, js.toUtf8().constData()); result_queue->enqueue(res->data.js_result.result, res->data.js_result.value); free_data(res); } break; case CMD_OPEN_DEVTOOLS: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktOpenDevtools(wv); result_queue->enqueue(r); } break; case CMD_MOVE: { int wv = data_obj["wv"].toInt(); int x = data_obj["x"].toInt(); int y = data_obj["y"].toInt(); result_t r = webview_handler->rktMove(wv, x, y); result_queue->enqueue(r); } break; case CMD_RESIZE: { int wv = data_obj["wv"].toInt(); int w = data_obj["w"].toInt(); int h = data_obj["h"].toInt(); result_t r = webview_handler->rktResize(wv, w, h); result_queue->enqueue(r); } break; case CMD_HIDE: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktHideWindow(wv); result_queue->enqueue(r); } break; case CMD_SHOW: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktShowWindow(wv); result_queue->enqueue(r); } break; case CMD_PRESENT: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktPresentWindow(wv); result_queue->enqueue(r); } break; case CMD_MAXIMIZE: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktMaximizeWindow(wv); result_queue->enqueue(r); } break; case CMD_MINIMIZE: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktMinimizeWindow(wv); result_queue->enqueue(r); } break; case CMD_SHOW_NORMAL: { int wv = data_obj["wv"].toInt(); result_t r = webview_handler->rktShowNormalWindow(wv); result_queue->enqueue(r); } break; case CMD_WINDOW_STATE: { int wv = data_obj["wv"].toInt(); window_state_t r = webview_handler->rktWindowState(wv); result_queue->enqueue(r); } break; case CMD_SET_TITLE: { int wv = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); result_t r = webview_handler->rktWindowSetTitle(wv, title.toUtf8().constData()); result_queue->enqueue(r); } break; case CMD_CHOOSE_DIR: { int wv = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); QString base_dir = data_obj["base_dir"].toString(); result_t r = webview_handler->rktChooseDir(wv, title.toUtf8().constData(), base_dir.toUtf8().constData() ); result_queue->enqueue(r); } break; case CMD_FILE_OPEN: { int wv = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); QString base_dir = data_obj["base_dir"].toString(); QString permitted_exts = data_obj["permitted_exts"].toString(); result_t r = webview_handler->rktFileOpen(wv, title.toUtf8().constData(), base_dir.toUtf8().constData(), permitted_exts.toUtf8().constData() ); result_queue->enqueue(r); } break; case CMD_FILE_SAVE: { int wv = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); QString base_dir = data_obj["base_dir"].toString(); QString permitted_exts = data_obj["permitted_exts"].toString(); result_t r = webview_handler->rktFileSave(wv, title.toUtf8().constData(), base_dir.toUtf8().constData(), permitted_exts.toUtf8().constData() ); result_queue->enqueue(r); } break; case CMD_SET_OU_TOKEN: { int wv = data_obj["wv"].toInt(); QString token = data_obj["token"].toString(); webview_handler->rktSetOUToken(wv, token.toUtf8().constData()); } break; case CMD_MSG_BOX: { int wv = data_obj["wv"].toInt(); QString title = data_obj["title"].toString(); QString message = data_obj["message"].toString(); QString submsg = data_obj["submessage"].toString(); int type = data_obj["type"].toInt(); result_t r = webview_handler->rktMessageBox(wv, title.toUtf8().constData(), message.toUtf8().constData(), submsg.toUtf8().constData(), static_cast(type) ); result_queue->enqueue(r); } break; default: { ERROR1("Unknown command: %d\n", cmd); } } } }