Much work, using Qt 6.10 on Linux for better https support

This commit is contained in:
2026-03-11 17:57:55 +01:00
parent 989c3d328a
commit 7d234bc834
16 changed files with 541 additions and 217 deletions

View File

@@ -26,6 +26,7 @@
#define COMMAND_FILE_OPEN 20
#define COMMAND_FILE_SAVE 21
#define COMMAND_SET_OU_TOKEN 22
#define COMMAND_SET_CERTIFICATE 23
class Command
{

View File

@@ -1,14 +1,15 @@
#include "rktwebview.h"
#include <QThread>
#include <QFile>
static int _argc;
static char **_argv;
void eventCb(rkt_event_t *e)
void eventCb(rkt_data_t *e)
{
printf("event: %s\n", e->event);
rkt_webview_destroy_event(e);
printf("event: %s\n", e->data.event.event);
rkt_webview_free_data(e);
}
int main(int argc, char *argv[])
@@ -20,7 +21,9 @@ int main(int argc, char *argv[])
_argv = argv;
rkt_webview_init();
wv1 = rkt_webview_create(0, eventCb);
wv1 = rkt_webview_create(0, eventCb, nullptr);
rkt_webview_move(wv1, 200, 300);
rkt_webview_resize(wv1, 800, 600);
rkt_webview_set_url(wv1, "https://wikipedia.org"); //"http://127.0.0.1:8083");
@@ -35,23 +38,26 @@ int main(int argc, char *argv[])
}
if (i == 3) {
rkt_js_result_t *r = rkt_webview_call_js(wv1, "{ let a = 7 * 6; console.log('a = ' + a); return a; }");
printf("rkt_js_result: %d: %s\n", r->result, r->value);
rkt_data_t *r = rkt_webview_call_js(wv1, "{ let a = 7 * 6; console.log('a = ' + a); return a; }");
printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
rkt_webview_free_data(r);
}
if (i == 4) {
rkt_js_result_t *r = rkt_webview_call_js(wv1, "let el = document.getElementById('hi');el.value = '10';");
printf("rkt_js_result: %d: %s\n", r->result, r->value);
rkt_data_t *r = rkt_webview_call_js(wv1, "let el = document.getElementById('hi');el.value = '10';");
printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
rkt_webview_free_data(r);
}
if (i == 6) {
rkt_js_result_t *r = rkt_webview_call_js(wv1, "document.body.innerHTML = '<h1>Hi!</h1>'; return document.body.innerHTML;");
printf("rkt_js_result: %d: %s\n", r->result, r->value);
rkt_data_t *r = rkt_webview_call_js(wv1, "document.body.innerHTML = '<h1>Hi!</h1>'; return document.body.innerHTML;");
printf("rkt_js_result: %d: %s\n", r->data.js_result.result, r->data.js_result.value);
rkt_webview_free_data(r);
}
if (i == 10) {
wv2 = rkt_webview_create(wv1, eventCb);
wv2 = rkt_webview_create(wv1, eventCb, nullptr);
rkt_webview_move(wv2, 400, 200);
rkt_webview_resize(wv2, 800, 600);
rkt_webview_set_url(wv2, "https://127.0.0.1");

View File

@@ -32,10 +32,10 @@ void rkt_webview_init()
}
}
int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb)
int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb, const char *optional_server_cert_pem)
{
rkt_webview_init();
return handler->rktWebViewCreate(parent, js_event_cb);
return handler->rktWebViewCreate(parent, js_event_cb, optional_server_cert_pem);
}
void rkt_webview_close(rktwebview_t wv)
@@ -66,10 +66,10 @@ result_t rkt_webview_run_js(rktwebview_t wv, const char *js)
return r;
}
rkt_js_result_t *rkt_webview_call_js(rktwebview_t wv, const char *js)
rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js)
{
rkt_webview_init();
rkt_js_result_t *r = handler->rktCallJs(wv, js);
rkt_data_t *r = handler->rktCallJs(wv, js);
return r;
}
@@ -95,22 +95,6 @@ void rkt_webview_process_events(int for_ms)
}
}
result_t rkt_webview_destroy_event(rkt_event_t *e)
{
free(e->event);
free(e);
return result_t::oke;
}
result_t rkt_webview_destroy_js_result(rkt_js_result_t *r)
{
free(r->value);
free(r);
return result_t::oke;
}
result_t rkt_webview_move(rktwebview_t wv, int x, int y)
{
rkt_webview_init();
@@ -184,19 +168,19 @@ result_t rkt_webview_set_title(rktwebview_t wv, const char *title)
return handler->rktWindowSetTitle(wv, title);
}
rkt_js_result_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir)
rkt_data_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir)
{
rkt_webview_init();
return handler->rktChooseDir(w, title, base_dir);
}
rkt_js_result_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
rkt_data_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
rkt_webview_init();
return handler->rktFileOpen(w, title, base_dir, permitted_exts);
}
rkt_js_result_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
rkt_data_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
rkt_webview_init();
return handler->rktFileSave(w, title, base_dir, permitted_exts);
@@ -207,3 +191,31 @@ void rkt_webview_set_ou_token(rktwebview_t wv, const char *token)
rkt_webview_init();
handler->rktSetOUToken(wv, token);
}
void rkt_webview_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 {
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);
}
}
rkt_data_t *rkt_webview_version()
{
rkt_data_t *d = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
d->kind = version;
d->data.version.api_major = RKT_WEBVIEW_API_MAJOR;
d->data.version.api_minor = RKT_WEBVIEW_API_MINOR;
d->data.version.api_patch = RKT_WEBVIEW_API_PATCH;
d->data.version.qt_major = QT_VERSION_MAJOR;
d->data.version.qt_minor = QT_VERSION_MINOR;
d->data.version.qt_patch = QT_VERSION_PATCH;
return d;
}

View File

@@ -3,6 +3,10 @@
#include "rktwebview_qt_global.h"
#define RKT_WEBVIEW_API_MAJOR 0
#define RKT_WEBVIEW_API_MINOR 1
#define RKT_WEBVIEW_API_PATCH 1
extern "C" {
typedef int rktwebview_t;
@@ -12,8 +16,6 @@ typedef struct {
char *event;
} rkt_event_t;
typedef void (*event_cb_t)(rkt_event_t *);
typedef enum {
no_result_yet = -1,
oke = 0,
@@ -51,27 +53,53 @@ typedef enum {
maximized_active = 18
} window_state_t;
typedef struct {
int qt_major;
int qt_minor;
int qt_patch;
int api_major;
int api_minor;
int api_patch;
} rkt_version_t;
typedef enum {
version = 1,
event = 2,
js_result = 3
} rkt_data_kind_t;
typedef struct {
rkt_data_kind_t kind;
union {
rkt_version_t version;
rkt_event_t event;
rkt_js_result_t js_result;
} data;
} rkt_data_t;
typedef void (*event_cb_t)(rkt_data_t *);
RKTWEBVIEW_QT_EXPORT void rkt_webview_init();
RKTWEBVIEW_QT_EXPORT void rkt_webview_process_events(int for_ms);
RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb);
RKTWEBVIEW_QT_EXPORT void rkt_webview_free_data(rkt_data_t *d);
RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_version();
RKTWEBVIEW_QT_EXPORT int rkt_webview_create(rktwebview_t parent, event_cb_t js_event_cb, const char *optional_server_cert_pem);
RKTWEBVIEW_QT_EXPORT void rkt_webview_close(rktwebview_t wv);
RKTWEBVIEW_QT_EXPORT bool rkt_webview_valid(rktwebview_t wv);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_title(rktwebview_t wv, const char *title);
RKTWEBVIEW_QT_EXPORT void rkt_webview_set_ou_token(rktwebview_t wv, const char *token);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_url(rktwebview_t wv, const char *url);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_set_html(rktwebview_t wv, const char *html);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_run_js(rktwebview_t wv, const char *js);
RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_call_js(rktwebview_t wv, const char *js);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_js_result(rkt_js_result_t *r);
RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_open_devtools(rktwebview_t wv);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_destroy_event(rkt_event_t *e);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_move(rktwebview_t w, int x, int y);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_resize(rktwebview_t w, int width, int height);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_hide(rktwebview_t w);
@@ -82,9 +110,9 @@ RKTWEBVIEW_QT_EXPORT result_t rkt_webview_maximize(rktwebview_t w);
RKTWEBVIEW_QT_EXPORT result_t rkt_webview_minimize(rktwebview_t w);
RKTWEBVIEW_QT_EXPORT window_state_t rkt_webview_window_state(rktwebview_t w);
RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir);
RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
RKTWEBVIEW_QT_EXPORT rkt_js_result_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_choose_dir(rktwebview_t w, const char *title, const char *base_dir);
RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_file_open(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
RKTWEBVIEW_QT_EXPORT rkt_data_t *rkt_webview_file_save(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
}

View File

@@ -12,6 +12,14 @@
#include "command.h"
#include <QFileDialog>
static inline char *copyString(const char *s)
{
int l = strlen(s);
char *cpy = static_cast<char *>(malloc(l + 1));
memcpy(cpy, s, l + 1);
return cpy;
}
void Rktwebview_qt::processCommand(Command *cmd)
{
switch(cmd->cmd) {
@@ -26,6 +34,9 @@ void Rktwebview_qt::processCommand(Command *cmd)
void *f = cmd->args[1].value<void *>();
event_cb_t js_event_cb = reinterpret_cast <event_cb_t>(f);
bool has_scp = cmd->args[2].toBool();
QByteArray scp_pem = cmd->args[3].toByteArray();
WebviewWindow *p;
if (_views.contains(parent)) {
p = _views[parent];
@@ -33,7 +44,7 @@ void Rktwebview_qt::processCommand(Command *cmd)
p = nullptr;
}
WebviewWindow *w = new WebviewWindow(p);
WebviewWindow *w = new WebviewWindow(p, has_scp, scp_pem);
WebViewQt *view = new WebViewQt(nextHandle(), w);
w->addView(view, this);
@@ -359,13 +370,17 @@ int Rktwebview_qt::nextHandle()
return h;
}
int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb)
int Rktwebview_qt::rktWebViewCreate(int parent, event_cb_t js_evt_cb, const char *optional_server_cert_pem)
{
Command c(COMMAND_CREATE);
c.args.push_back(parent);
void *function = reinterpret_cast<void *>(js_evt_cb);
QVariant f(QVariant::fromValue(function));
c.args.push_back(f);
bool has_scp = (optional_server_cert_pem != nullptr);
c.args.push_back(has_scp);
QByteArray scp = (optional_server_cert_pem == nullptr) ? QByteArray("") : QByteArray(optional_server_cert_pem);
c.args.push_back(scp);
postCommand(&c);
@@ -427,7 +442,7 @@ result_t Rktwebview_qt::rktSetHtml(rktwebview_t wv, const char *html)
return r ? result_t::oke : result_t::set_html_failed;
}
rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
rkt_data_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
{
Command c(COMMAND_CALL_JS);
QString _js(js);
@@ -436,9 +451,10 @@ rkt_js_result_t *Rktwebview_qt::rktCallJs(rktwebview_t wv, const char *js)
postCommand(&c);
while(!c.done) { doEvents(); }
rkt_js_result_t *r = static_cast<rkt_js_result_t *>(malloc(sizeof(rkt_js_result_t)));
r->result = c.js_result_ok ? result_t::oke : result_t::eval_js_failed;
r->value = strdup(c.result.toString().toUtf8());
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::eval_js_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
@@ -520,7 +536,7 @@ window_state_t Rktwebview_qt::rktWindowState(rktwebview_t w)
return ws;
}
rkt_js_result_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
rkt_data_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
{
Command c(COMMAND_CHOOSE_DIR);
c.args.push_back(w);
@@ -537,15 +553,15 @@ rkt_js_result_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title,
bool oke = c.js_result_ok;
rkt_js_result_t *r = static_cast<rkt_js_result_t *>(malloc(sizeof(rkt_js_result_t)));
r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->value = strdup(c.result.toString().toUtf8());
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_js_result_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
rkt_js_result_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
rkt_data_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
Command c(COMMAND_FILE_OPEN);
c.args.push_back(w);
@@ -565,15 +581,15 @@ rkt_js_result_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, c
bool oke = c.js_result_ok;
rkt_js_result_t *r = static_cast<rkt_js_result_t *>(malloc(sizeof(rkt_js_result_t)));
r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->value = strdup(c.result.toString().toUtf8());
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
rkt_js_result_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
rkt_data_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
Command c(COMMAND_FILE_SAVE);
c.args.push_back(w);
@@ -593,10 +609,10 @@ rkt_js_result_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, c
bool oke = c.js_result_ok;
rkt_js_result_t *r = static_cast<rkt_js_result_t *>(malloc(sizeof(rkt_js_result_t)));
r->result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->value = strdup(c.result.toString().toUtf8());
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
}
@@ -672,11 +688,12 @@ void Rktwebview_qt::triggerEvent(rktwebview_t wv, const QString &msg)
{
if (_view_js_callbacks.contains(wv)) {
event_cb_t js_event_cb = _view_js_callbacks[wv];
char *evt = strdup(msg.toUtf8().constData());
rkt_event_t *e = static_cast<rkt_event_t *>(malloc(sizeof(rkt_event_t)));
e->wv = wv;
e->event = evt;
js_event_cb(e);
char *evt = copyString(msg.toUtf8().constData());
rkt_data_t *d = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
d->kind = rkt_data_kind_t::event;
d->data.event.wv = wv;
d->data.event.event = evt;
js_event_cb(d);
}
}
@@ -726,21 +743,29 @@ void Rktwebview_qt::customEvent(QEvent *event)
void Rktwebview_qt::doEvents()
{
//_app->processEvents();
if (_evt_loop_depth == 0) {
//QTime ct = QTime::currentTime();
//QTime expire = QTime::currentTime().addMSecs(2);
//while(QTime::currentTime() <= expire) {
_app->processEvents();
//}
// Qt 6.10 --> this leads to a core dump
// together with the stopEventloop stuff.
// Qt 6.4 seem stable.
/*if (_evt_loop_depth == 0) {
_evt_loop_depth += 1;
_evt_loop_timer.setSingleShot(true);
_evt_loop_timer.start(2);
//_evt_loop.exec();
_app->exec();
}
}*/
}
void Rktwebview_qt::stopEventloop()
{
//_evt_loop.exit(0);
_app->exit(0);
_evt_loop_depth -= 1;
//_app->exit(0);
//_evt_loop_depth -= 1;
}
@@ -760,15 +785,18 @@ Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) :
connect(&_process_events, &QTimer::timeout, this, &Rktwebview_qt::processJsEventQueues);
_process_events.start(5);
connect(&_evt_loop_timer, &QTimer::timeout, this, &Rktwebview_qt::stopEventloop);
// See Qt 6.10 remark at doEvents.
//connect(&_evt_loop_timer, &QTimer::timeout, this, &Rktwebview_qt::stopEventloop);
//const auto *eventDispatcher = QThread::currentThread()->eventDispatcher();
//QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock,
// QThread::currentThread(), []{
// if (QThread::currentThread()->loopLevel() == 0)
// QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
// }
// );
// Because we are using processEvents only (Qt 6.10), we need this dispatcher to
// handle deferred Deletes.
const auto *eventDispatcher = QThread::currentThread()->eventDispatcher();
QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock,
QThread::currentThread(), []{
if (QThread::currentThread()->loopLevel() == 0)
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
}
);
*_handler = nullptr;
}

View File

@@ -64,7 +64,7 @@ public:
public:
int nextHandle();
public:
int rktWebViewCreate(int parent, event_cb_t js_evt_cb);
int rktWebViewCreate(int parent, event_cb_t js_evt_cb, const char *optional_server_cert_pem);
void rktWebViewClose(int wv);
void rktSetOUToken(rktwebview_t wv, const char *ou_token);
void rktQuit();
@@ -73,7 +73,7 @@ public:
result_t rktSetUrl(rktwebview_t wv, const char *url);
result_t rktSetHtml(rktwebview_t wv, const char *html);
result_t rktRunJs(rktwebview_t wv, const char *js);
rkt_js_result_t *rktCallJs(rktwebview_t wv, const char *js);
rkt_data_t *rktCallJs(rktwebview_t wv, const char *js);
result_t rktMove(rktwebview_t wv, int x, int y);
result_t rktResize(rktwebview_t wv, int w, int h);
@@ -85,9 +85,9 @@ public:
result_t rktShowNormalWindow(rktwebview_t w);
window_state_t rktWindowState(rktwebview_t w);
rkt_js_result_t *rktChooseDir(rktwebview_t w, const char *title, const char *base_dir);
rkt_js_result_t * rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
rkt_js_result_t * rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
rkt_data_t *rktChooseDir(rktwebview_t w, const char *title, const char *base_dir);
rkt_data_t *rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
rkt_data_t *rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts);
result_t rktWindowSetTitle(rktwebview_t wv, const char *title);
@@ -110,7 +110,7 @@ public:
public:
Rktwebview_qt(Rktwebview_qt **handler);
};
};

View File

@@ -4,7 +4,7 @@
#include <QJsonDocument>
WebViewQt::WebViewQt(int id, WebviewWindow *window)
: QWebEngineView(window)
: QWebEngineView(window->profile(), window)
{
_id = id;
_window = window;

View File

@@ -10,13 +10,37 @@
#include <QJsonObject>
#include <QWebEngineScriptCollection>
#include <QWebEngineScript>
#include <QWebEngineProfile>
#include <QWebEngineProfileBuilder>
#include <QWebEnginePage>
#include <QMoveEvent>
#include <QWindow>
#include <QWebEngineProfileBuilder>
WebviewWindow::WebviewWindow(WebviewWindow *parent)
/*
static void displ(QSslCertificate & cert, QSslCertificate::SubjectInfo &a) {
QStringList issuerInfo = cert.issuerInfo(a);
int i, N;
printf("%d\n", a);
for(i = 0, N = issuerInfo.size(); i < N; i++) {
printf("%d[%d]: %s\n", a, i, issuerInfo[i].toUtf8().constData());
}
};
static void displ1(QSslCertificate &cert, QList<QSslCertificate::SubjectInfo > l) {
int i, N;
for(i = 0, N = l.size(); i < N; i++) {
displ(cert, l[i]);
}
};
*/
WebviewWindow::WebviewWindow(WebviewWindow *parent, bool has_scp, QByteArray scp_pem)
: QMainWindow{parent}
{
static int profile_nr = 0;
_view = nullptr;
_must_close = false;
@@ -27,6 +51,22 @@ WebviewWindow::WebviewWindow(WebviewWindow *parent)
_moved = 0;
_resized = 0;
QWebEngineProfileBuilder b;
if (has_scp) {
profile_nr += 1;
char buf[100];
sprintf(buf, "profile-%d", profile_nr);
QString name(buf);
QSslCertificate cert(scp_pem);
QList<QSslCertificate> certs;
certs.append(cert);
b.setAdditionalTrustedCertificates(certs);
_profile = b.createProfile(name);
} else {
_profile = QWebEngineProfile::defaultProfile();
}
if (parent != nullptr) {
setWindowModality(Qt::WindowModality::WindowModal);
setWindowFlag(Qt::WindowType::Dialog, true);
@@ -36,9 +76,63 @@ WebviewWindow::WebviewWindow(WebviewWindow *parent)
connect(&_move_timer, &QTimer::timeout, this, &WebviewWindow::triggerMove);
}
void WebviewWindow::navigationRequested(QWebEngineNavigationRequest &req)
{
if (req.navigationType() == QWebEngineNavigationRequest::NavigationType::TypedNavigation) {
req.accept();
} else {
EventContainer e("navigation-request");
e["url"] = req.url().toString();
QString type;
switch (req.navigationType()) {
case QWebEngineNavigationRequest::NavigationType::LinkClickedNavigation: type = "link-clicked";
break;
case QWebEngineNavigationRequest::NavigationType::TypedNavigation: type = "typed";
break;
case QWebEngineNavigationRequest::NavigationType::FormSubmittedNavigation: type = "form-submit";
break;
case QWebEngineNavigationRequest::NavigationType::BackForwardNavigation: type = "back-or-forward";
break;
case QWebEngineNavigationRequest::NavigationType::ReloadNavigation: type = "reload";
break;
case QWebEngineNavigationRequest::NavigationType::RedirectNavigation: type = "redirect";
break;
default: type = "other";
break;
}
e["type"] = type;
_container->triggerEvent(_view->id(), e);
req.reject();
}
}
void WebviewWindow::handleCertificate(const QWebEngineCertificateError &certificateError)
{
/*
QList<QSslCertificate> certs = _view->page()->profile()->additionalTrustedCertificates();
auto dodisp = [](QList<QSslCertificate> certs)
{
int i;
for(i = 0; i < certs.size(); i++) {
QSslCertificate cert = certs[i];
QList<QSslCertificate::SubjectInfo> attrs;
attrs.append(QSslCertificate::Organization);
attrs.append(QSslCertificate::OrganizationalUnitName);
attrs.append(QSslCertificate::CountryName);
attrs.append(QSslCertificate::CommonName);
displ1(cert, attrs);
}
};
dodisp(certs);
dodisp(certificateError.certificateChain());
*/
fprintf(stderr, "Certificate Error: %s\n", certificateError.description().toUtf8().constData());
QList<QSslCertificate> chain = certificateError.certificateChain();
int i;
for(i = 0; i < chain.size(); i++) {
@@ -88,6 +182,7 @@ void WebviewWindow::closeEvent(QCloseEvent *evt)
EventContainer e("closed");
_container->triggerEvent(_view->id(), e);
_container->removeView(_view->id());
_view->deleteLater();
this->deleteLater();
if (_devtools != nullptr) {
_devtools->deleteLater();
@@ -131,7 +226,14 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
_view = v;
this->setCentralWidget(v);
QWebEnginePage *page = _view->page();
QWebEnginePage *page;
if (_profile == nullptr) {
page = _view->page();
} else {
page = new QWebEnginePage(_profile, this);
_view->setPage(page);
}
// Inject event handling code for the javascript side
QWebEngineScriptCollection &col = page->scripts();
@@ -160,6 +262,8 @@ void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
connect(page, &QWebEnginePage::loadStarted, this, [this]() {
_container->onPageLoad(_view->id());
});
connect(page, &QWebEnginePage::navigationRequested, this, &WebviewWindow::navigationRequested);
connect(page, &QWebEnginePage::certificateError, this, &WebviewWindow::handleCertificate);
}
@@ -231,6 +335,11 @@ void WebviewWindow::triggerMove()
_container->triggerEvent(_view->id(), xy);
}
QWebEngineProfile *WebviewWindow::profile()
{
return _profile;
}
void WebviewWindow::resizeEvent(QResizeEvent *event)
{
_w = event->size().width();

View File

@@ -4,6 +4,8 @@
#include <QMainWindow>
#include <QTimer>
#include <QWebEngineCertificateError>
#include <QWebEngineProfile>
#include <QWebEngineNavigationRequest>
class WebViewQt;
class Rktwebview_qt;
@@ -33,8 +35,11 @@ private:
QString _ou_token;
QWebEngineProfile *_profile;
private slots:
void handleCertificate(const QWebEngineCertificateError &certificateError);
void navigationRequested(QWebEngineNavigationRequest &req);
public slots:
void processJsEvents();
@@ -60,12 +65,15 @@ public:
void openDevTools();
public:
explicit WebviewWindow(WebviewWindow *parent = nullptr);
explicit WebviewWindow(WebviewWindow *parent, bool has_scp, QByteArray scp_pem);
private slots:
void triggerResize();
void triggerMove();
public:
QWebEngineProfile *profile();
signals:
// QWidget interface