Omzetting naar stdio.
This commit is contained in:
@@ -1,494 +1,461 @@
|
||||
#include <QThread>
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
|
||||
#include "rkt_protocol.h"
|
||||
#include "shm.h"
|
||||
#include "shmqueue.h"
|
||||
#include "command.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QThread>
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "rkt_protocol.h"
|
||||
#include "rktwebview_qt.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef DEBUG_RKT_WEBVIEW
|
||||
#define WAIT_TIME (300 * 1000)
|
||||
#else
|
||||
#define WAIT_TIME (10 * 1000)
|
||||
#endif
|
||||
constexpr int STDIO_PROTOCOL_VERSION = 1;
|
||||
|
||||
static void free_data(rkt_data_t *d)
|
||||
std::mutex output_mutex;
|
||||
|
||||
void writeMessage(const QJsonObject &message)
|
||||
{
|
||||
do_free_data(d);
|
||||
const QByteArray json = QJsonDocument(message).toJson(QJsonDocument::Compact);
|
||||
std::lock_guard<std::mutex> lock(output_mutex);
|
||||
std::cout.write(json.constData(), json.size());
|
||||
std::cout.put('\n');
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
void sendReady()
|
||||
{
|
||||
QJsonObject message;
|
||||
message["type"] = "ready";
|
||||
message["protocol"] = STDIO_PROTOCOL_VERSION;
|
||||
writeMessage(message);
|
||||
}
|
||||
|
||||
void sendResult(int id,
|
||||
int result,
|
||||
const QJsonValue &data = QJsonValue(QJsonValue::Null))
|
||||
{
|
||||
QJsonObject message;
|
||||
message["type"] = "result";
|
||||
message["id"] = id;
|
||||
message["result"] = result;
|
||||
message["data"] = data;
|
||||
writeMessage(message);
|
||||
}
|
||||
|
||||
void sendProtocolError(const QString &messageText, int id = -1)
|
||||
{
|
||||
QJsonObject message;
|
||||
message["type"] = "protocol-error";
|
||||
if (id >= 0) {
|
||||
message["id"] = id;
|
||||
}
|
||||
message["message"] = messageText;
|
||||
writeMessage(message);
|
||||
}
|
||||
|
||||
void freeData(rkt_data_t *data)
|
||||
{
|
||||
do_free_data(data);
|
||||
}
|
||||
|
||||
class Handler : public QThread
|
||||
{
|
||||
public:
|
||||
Shm *shm;
|
||||
ShmQueue *command_queue;
|
||||
ShmQueue *result_queue;
|
||||
ShmQueue *event_queue;
|
||||
Rktwebview_qt *webview_handler;
|
||||
bool quit;
|
||||
|
||||
// QThread interface
|
||||
protected:
|
||||
void run();
|
||||
};
|
||||
|
||||
class Alive : public QThread
|
||||
{
|
||||
public:
|
||||
Handler *handler;
|
||||
ShmQueue *alive_queue;
|
||||
ShmQueue *alive_ack_queue;
|
||||
bool alive_timeout;
|
||||
Rktwebview_qt *webviewHandler = nullptr;
|
||||
|
||||
protected:
|
||||
void run();
|
||||
void run() override;
|
||||
};
|
||||
|
||||
static Handler *_handler;
|
||||
static Alive *_alive;
|
||||
|
||||
static void event_cb(rkt_data_t *data)
|
||||
void eventCallback(rkt_data_t *data)
|
||||
{
|
||||
if (data->kind != rkt_data_kind_t::event) {
|
||||
if (data == nullptr || data->kind != rkt_data_kind_t::event) {
|
||||
freeData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
int wv = data->data.event.wv;
|
||||
char *evt = data->data.event.event;
|
||||
QJsonObject message;
|
||||
message["type"] = "event";
|
||||
message["wv"] = data->data.event.wv;
|
||||
message["data"] = QString::fromUtf8(data->data.event.event);
|
||||
writeMessage(message);
|
||||
|
||||
std::string evt_d(evt);
|
||||
_handler->event_queue->enqueue(wv, evt_d);
|
||||
|
||||
free_data(data);
|
||||
freeData(data);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *me = argv[0];
|
||||
INFO0("Starting stdio backend\n");
|
||||
|
||||
{
|
||||
time_t my_time = time(NULL);
|
||||
INFO1("Starting at %s", ctime(&my_time));
|
||||
}
|
||||
Handler commandHandler;
|
||||
commandHandler.webviewHandler = new Rktwebview_qt(argc, argv);
|
||||
commandHandler.webviewHandler->initApp();
|
||||
commandHandler.start();
|
||||
|
||||
if (argc < 8) {
|
||||
ERROR1("%s: wrong number of arguments\n", me);
|
||||
exit(1);
|
||||
}
|
||||
sendReady();
|
||||
commandHandler.webviewHandler->execApp();
|
||||
|
||||
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];
|
||||
const char *alive_slot_str = argv[6];
|
||||
const char *alive_ack_slot_str = argv[7];
|
||||
INFO0("Qt event loop stopped; waiting for stdin handler\n");
|
||||
commandHandler.wait();
|
||||
|
||||
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);
|
||||
int alive_slot = atoi(alive_slot_str);
|
||||
int alive_ack_slot = atoi(alive_ack_slot_str);
|
||||
|
||||
MKLOGSTMT(LOG_INFO, fprintf(stderr, "%s %s %s %s %s %s %s %s\n", me, shm_name, shm_size_str,
|
||||
cmd_slot_str, res_slot_str, evt_slot_str, alive_slot_str, alive_ack_slot_str));
|
||||
MKLOGSTMT(LOG_INFO, fprintf(stderr, "%s %s %d %d %d %d %d %d\n", me, shm_name, static_cast<int>(shm_size),
|
||||
cmd_slot, res_slot, evt_slot, alive_slot, alive_ack_slot));
|
||||
|
||||
if (!(shm_size > 0 && cmd_slot > 0 && res_slot > 0 && evt_slot > 0 && alive_slot > 0 && alive_ack_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();
|
||||
|
||||
Alive *alive = new Alive();
|
||||
_alive = alive;
|
||||
alive->handler = handler;
|
||||
alive->alive_timeout = false;
|
||||
alive->alive_queue = new ShmQueue(handler->shm, alive_slot, false);
|
||||
alive->alive_ack_queue = new ShmQueue(handler->shm, alive_ack_slot, false);
|
||||
alive->start();
|
||||
|
||||
handler->webview_handler->initApp();
|
||||
handler->webview_handler->execApp();
|
||||
|
||||
INFO0("waiting for thread to end\n");
|
||||
handler->wait();
|
||||
INFO0("Handler thread stopped\n");
|
||||
alive->wait();
|
||||
INFO0("Alive thread stopped\n");
|
||||
|
||||
if (alive->alive_timeout) {
|
||||
// take ownership over all queues and SHM, because we didn't get an alive message
|
||||
// and probably the racket side has crashed because of that.
|
||||
ERROR0("Taking ownership of shared memory, shared queues and shared semaphores\n");
|
||||
handler->command_queue->takeOwnership();
|
||||
handler->result_queue->takeOwnership();
|
||||
handler->event_queue->takeOwnership();
|
||||
handler->shm->takeOwnership();
|
||||
alive->alive_queue->takeOwnership();
|
||||
alive->alive_ack_queue->takeOwnership();
|
||||
}
|
||||
|
||||
INFO0("cleaning up shm\n");
|
||||
|
||||
delete alive->alive_queue;
|
||||
delete alive;
|
||||
|
||||
delete handler->webview_handler;
|
||||
delete handler->command_queue;
|
||||
delete handler->result_queue;
|
||||
delete handler->event_queue;
|
||||
delete handler->shm;
|
||||
delete handler;
|
||||
|
||||
{
|
||||
time_t my_time = time(NULL);
|
||||
INFO1("Exiting at %s", ctime(&my_time));
|
||||
}
|
||||
delete commandHandler.webviewHandler;
|
||||
commandHandler.webviewHandler = nullptr;
|
||||
|
||||
INFO0("Exiting stdio backend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Handler::run()
|
||||
{
|
||||
int wait_ms = WAIT_TIME; // 10 seconds.
|
||||
while (!quit) {
|
||||
int cmd;
|
||||
std::string data;
|
||||
bool something_came = command_queue->dequeue(cmd, data, wait_ms);
|
||||
if (!something_came) {
|
||||
DEBUG1("No command received last %d seconds\n", wait_ms / 1000);
|
||||
cmd = CMD_NOOP;
|
||||
std::string line;
|
||||
bool quit = false;
|
||||
|
||||
while (!quit && std::getline(std::cin, line)) {
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
QJsonObject data_obj = QJsonDocument::fromJson(data.c_str()).object();
|
||||
|
||||
switch(cmd) {
|
||||
case CMD_NOOP: {
|
||||
if (quit) {
|
||||
DEBUG1("Alive timeout, quit = %d\n", quit);
|
||||
webview_handler->closeAllWindows();
|
||||
DEBUG0("Closed all windows\n");
|
||||
webview_handler->rktQuit();
|
||||
DEBUG0("Quit application\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
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_INFO: {
|
||||
int open_windows = webview_handler->openWindows();
|
||||
result_queue->enqueue(open_windows);
|
||||
}
|
||||
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_SET_LOGLEVEL: {
|
||||
int ll = data_obj["wv"].toInt();
|
||||
setLogLevel(ll);
|
||||
bool oke = true;
|
||||
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();
|
||||
QJsonParseError parseError;
|
||||
const QJsonDocument document =
|
||||
QJsonDocument::fromJson(QByteArray::fromStdString(line), &parseError);
|
||||
|
||||
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_SET_ICON: {
|
||||
int wv = data_obj["wv"].toInt();
|
||||
QString icon_file = data_obj["icon"].toString();
|
||||
result_t r = webview_handler->rktWindowSetIcon(wv, icon_file.toUtf8().constData());
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
case CMD_CREATE_TRAY: {
|
||||
QString icon_file = data_obj["icon"].toString();
|
||||
QString tooltip = data_obj["tooltip"].toString();
|
||||
|
||||
int tray = webview_handler->rktTrayCreate(icon_file.toUtf8().constData(),
|
||||
tooltip.toUtf8().constData(),
|
||||
event_cb);
|
||||
result_queue->enqueue(tray);
|
||||
}
|
||||
break;
|
||||
case CMD_TRAY_SET_ICON: {
|
||||
int tray = data_obj["wv"].toInt();
|
||||
QString icon_file = data_obj["icon"].toString();
|
||||
|
||||
result_t r = webview_handler->rktTraySetIcon(tray,
|
||||
icon_file.toUtf8().constData());
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
case CMD_TRAY_SET_TOOLTIP: {
|
||||
int tray = data_obj["wv"].toInt();
|
||||
QString tooltip = data_obj["tooltip"].toString();
|
||||
|
||||
result_t r = webview_handler->rktTraySetTooltip(tray,
|
||||
tooltip.toUtf8().constData());
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
case CMD_TRAY_SHOW_MESSAGE: {
|
||||
int tray = data_obj["wv"].toInt();
|
||||
QString title = data_obj["title"].toString();
|
||||
QString message = data_obj["message"].toString();
|
||||
|
||||
result_t r = webview_handler->rktTrayShowMessage(tray,
|
||||
title.toUtf8().constData(),
|
||||
message.toUtf8().constData());
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
case CMD_TRAY_CLEAR_MENU: {
|
||||
int tray = data_obj["wv"].toInt();
|
||||
result_t r = webview_handler->rktTraySetMenu(tray, nullptr);
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
case CMD_TRAY_SET_MENU: {
|
||||
int tray = data_obj["wv"].toInt();
|
||||
QString menu_json = data_obj["menu_json"].toString();
|
||||
|
||||
result_t r = webview_handler->rktTraySetMenu(tray,
|
||||
menu_json.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<rkt_messagetype_t>(type)
|
||||
);
|
||||
result_queue->enqueue(r);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
ERROR1("Unknown command: %d\n", cmd);
|
||||
}
|
||||
if (parseError.error != QJsonParseError::NoError || !document.isObject()) {
|
||||
const QString message = QString("Invalid protocol JSON: %1")
|
||||
.arg(parseError.errorString());
|
||||
ERROR1("%s\n", message.toUtf8().constData());
|
||||
sendProtocolError(message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
DEBUG0("Exiting handler thread\n");
|
||||
}
|
||||
|
||||
void Alive::run()
|
||||
{
|
||||
int wait_ms = WAIT_TIME;
|
||||
int ping_no;
|
||||
std::string data;
|
||||
bool go_on = true;
|
||||
while (go_on) {
|
||||
bool something_came = alive_queue->dequeue(ping_no, data, wait_ms);
|
||||
if (!something_came) {
|
||||
ERROR0("No alive message received, stopping alive loop and quitting rktwebview_prg\n");
|
||||
handler->quit = true;
|
||||
handler->command_queue->enqueue(CMD_NOOP);
|
||||
alive_timeout = true;
|
||||
go_on = false;
|
||||
} else {
|
||||
if (ping_no == CMD_ALIVE_QUIT) {
|
||||
DEBUG0("Got Quit ping for alive thread\n");
|
||||
go_on = false;
|
||||
const QJsonObject request = document.object();
|
||||
const int id = request["id"].toInt(-1);
|
||||
|
||||
if (request["type"].toString() != "command") {
|
||||
sendProtocolError("Expected a command message", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
const int command = request["command"].toInt(CMD_NOOP);
|
||||
const QJsonObject data = request["data"].toObject();
|
||||
|
||||
if (id < 0) {
|
||||
sendProtocolError("Command has no valid request id");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case CMD_NOOP:
|
||||
sendResult(id, result_t::oke);
|
||||
break;
|
||||
|
||||
case CMD_QUIT:
|
||||
INFO0("Got quit command\n");
|
||||
webviewHandler->rktQuit();
|
||||
sendResult(id, RESULT_QUIT);
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
case CMD_INFO:
|
||||
sendResult(id, webviewHandler->openWindows());
|
||||
break;
|
||||
|
||||
case CMD_HANDLE_IS_VALID: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktValid(wv) ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_LOGLEVEL: {
|
||||
const int level = data["wv"].toInt();
|
||||
setLogLevel(level);
|
||||
sendResult(id, result_t::oke);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CONTEXT_NEW: {
|
||||
const QString boilerplateJs = data["boilerplate_js"].toString();
|
||||
const bool hasPemCertificate = data["has_pem_cert"].toBool();
|
||||
const QString pemCertificate = data["pem_cert"].toString();
|
||||
const int context = webviewHandler->newContext(boilerplateJs,
|
||||
hasPemCertificate,
|
||||
pemCertificate);
|
||||
sendResult(id, context);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CREATE_WV: {
|
||||
const int context = data["context"].toInt();
|
||||
const int parent = data["parent"].toInt();
|
||||
const int wv = webviewHandler->rktWebViewCreate(context,
|
||||
parent,
|
||||
eventCallback);
|
||||
sendResult(id, wv);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CLOSE_WV: {
|
||||
const int wv = data["wv"].toInt();
|
||||
webviewHandler->rktWebViewClose(wv);
|
||||
sendResult(id, result_t::oke);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_URL: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString url = data["url"].toString();
|
||||
sendResult(id, webviewHandler->rktSetUrl(wv, url.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_HTML: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString html = data["html"].toString();
|
||||
sendResult(id, webviewHandler->rktSetHtml(wv, html.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_RUN_JS: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString js = data["js"].toString();
|
||||
sendResult(id, webviewHandler->rktRunJs(wv, js));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CALL_JS: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString js = data["js"].toString();
|
||||
rkt_data_t *response = webviewHandler->rktCallJs(wv, js.toUtf8().constData());
|
||||
if (response == nullptr || response->kind != rkt_data_kind_t::js_result) {
|
||||
sendResult(id, result_t::failed, "Missing JavaScript result");
|
||||
} else {
|
||||
DEBUG1("Got alive ping: %d\n", ping_no);
|
||||
alive_ack_queue->enqueue(ping_no);
|
||||
sendResult(id,
|
||||
response->data.js_result.result,
|
||||
QString::fromUtf8(response->data.js_result.value));
|
||||
}
|
||||
freeData(response);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_OPEN_DEVTOOLS: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktOpenDevtools(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_MOVE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id,
|
||||
webviewHandler->rktMove(wv,
|
||||
data["x"].toInt(),
|
||||
data["y"].toInt()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_RESIZE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id,
|
||||
webviewHandler->rktResize(wv,
|
||||
data["w"].toInt(),
|
||||
data["h"].toInt()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_HIDE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktHideWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SHOW: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktShowWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_PRESENT: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktPresentWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_MAXIMIZE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktMaximizeWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_MINIMIZE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktMinimizeWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SHOW_NORMAL: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktShowNormalWindow(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_WINDOW_STATE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktWindowState(wv));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_TITLE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktWindowSetTitle(wv,
|
||||
title.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_ICON: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString icon = data["icon"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktWindowSetIcon(wv,
|
||||
icon.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CREATE_TRAY: {
|
||||
const QString icon = data["icon"].toString();
|
||||
const QString tooltip = data["tooltip"].toString();
|
||||
const int tray = webviewHandler->rktTrayCreate(icon.toUtf8().constData(),
|
||||
tooltip.toUtf8().constData(),
|
||||
eventCallback);
|
||||
sendResult(id, tray);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TRAY_SET_ICON: {
|
||||
const int tray = data["wv"].toInt();
|
||||
const QString icon = data["icon"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktTraySetIcon(tray,
|
||||
icon.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TRAY_SET_TOOLTIP: {
|
||||
const int tray = data["wv"].toInt();
|
||||
const QString tooltip = data["tooltip"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktTraySetTooltip(tray,
|
||||
tooltip.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TRAY_SHOW_MESSAGE: {
|
||||
const int tray = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
const QString message = data["message"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktTrayShowMessage(tray,
|
||||
title.toUtf8().constData(),
|
||||
message.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TRAY_CLEAR_MENU: {
|
||||
const int tray = data["wv"].toInt();
|
||||
sendResult(id, webviewHandler->rktTraySetMenu(tray, nullptr));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TRAY_SET_MENU: {
|
||||
const int tray = data["wv"].toInt();
|
||||
const QString menuJson = data["menu_json"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktTraySetMenu(tray,
|
||||
menuJson.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CHOOSE_DIR: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
const QString baseDir = data["base_dir"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktChooseDir(wv,
|
||||
title.toUtf8().constData(),
|
||||
baseDir.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_FILE_OPEN: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
const QString baseDir = data["base_dir"].toString();
|
||||
const QString permittedExtensions = data["permitted_exts"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktFileOpen(wv,
|
||||
title.toUtf8().constData(),
|
||||
baseDir.toUtf8().constData(),
|
||||
permittedExtensions.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_FILE_SAVE: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
const QString baseDir = data["base_dir"].toString();
|
||||
const QString permittedExtensions = data["permitted_exts"].toString();
|
||||
sendResult(id,
|
||||
webviewHandler->rktFileSave(wv,
|
||||
title.toUtf8().constData(),
|
||||
baseDir.toUtf8().constData(),
|
||||
permittedExtensions.toUtf8().constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_SET_OU_TOKEN: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString token = data["token"].toString();
|
||||
webviewHandler->rktSetOUToken(wv, token.toUtf8().constData());
|
||||
sendResult(id, result_t::oke);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_MSG_BOX: {
|
||||
const int wv = data["wv"].toInt();
|
||||
const QString title = data["title"].toString();
|
||||
const QString message = data["message"].toString();
|
||||
const QString submessage = data["submessage"].toString();
|
||||
const auto type = static_cast<rkt_messagetype_t>(data["type"].toInt());
|
||||
sendResult(id,
|
||||
webviewHandler->rktMessageBox(wv,
|
||||
title.toUtf8().constData(),
|
||||
message.toUtf8().constData(),
|
||||
submessage.toUtf8().constData(),
|
||||
type));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
const QString message = QString("Unknown command: %1").arg(command);
|
||||
ERROR1("%s\n", message.toUtf8().constData());
|
||||
sendResult(id, result_t::failed, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG0("Exiting alive thread\n");
|
||||
|
||||
if (!quit) {
|
||||
INFO0("stdin closed; stopping Qt backend\n");
|
||||
webviewHandler->closeAllWindows();
|
||||
webviewHandler->rktQuit();
|
||||
}
|
||||
|
||||
DEBUG0("Exiting stdin handler\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user