372 lines
10 KiB
C++
372 lines
10 KiB
C++
#include "webviewwindow.h"
|
|
#include "utils.h"
|
|
|
|
#include "webviewqt.h"
|
|
#include "rktwebview_qt.h"
|
|
#include "rktutils.h"
|
|
#include "command.h"
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QJsonParseError>
|
|
#include <QJsonObject>
|
|
#include <QWebEngineScriptCollection>
|
|
#include <QWebEngineScript>
|
|
#include <QWebEngineProfile>
|
|
#include <QWebEngineProfileBuilder>
|
|
#include <QWebEnginePage>
|
|
#include <QMoveEvent>
|
|
#include <QWindow>
|
|
#include <QWebEngineProfileBuilder>
|
|
|
|
|
|
/*
|
|
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(QWebEngineProfile *profile, WebviewWindow *parent)
|
|
: QMainWindow{parent}
|
|
{
|
|
static int profile_nr = 0;
|
|
|
|
_view = nullptr;
|
|
_must_close = false;
|
|
|
|
_devtools = nullptr;
|
|
_parent = parent;
|
|
|
|
_window_created = false;
|
|
_moved = 0;
|
|
_resized = 0;
|
|
|
|
_profile = profile;
|
|
_navigation_event_sent = false;
|
|
|
|
if (parent != nullptr) {
|
|
setWindowModality(Qt::WindowModality::WindowModal);
|
|
setWindowFlag(Qt::WindowType::Dialog, true);
|
|
}
|
|
|
|
connect(&_resize_timer, &QTimer::timeout, this, &WebviewWindow::triggerResize);
|
|
connect(&_move_timer, &QTimer::timeout, this, &WebviewWindow::triggerMove);
|
|
}
|
|
|
|
void WebviewWindow::navigationRequested(QWebEngineNavigationRequest &req)
|
|
{
|
|
QWebEngineNavigationRequest::NavigationType t = req.navigationType();
|
|
if (t == QWebEngineNavigationRequest::NavigationType::TypedNavigation ||
|
|
t == QWebEngineNavigationRequest::RedirectNavigation) {
|
|
_navigation_event_sent = false;
|
|
req.accept();
|
|
} else {
|
|
EventContainer e("navigation-request");
|
|
|
|
QString u = req.url().toString();
|
|
|
|
e["url"] = u;
|
|
|
|
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);
|
|
|
|
_navigation_event_sent = true;
|
|
|
|
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());
|
|
*/
|
|
|
|
ERROR1("Certificate Error: %s\n", certificateError.description().toUtf8().constData());
|
|
QList<QSslCertificate> chain = certificateError.certificateChain();
|
|
int i;
|
|
for(i = 0; i < chain.size(); i++) {
|
|
const QSslCertificate &cert = chain[i];
|
|
if (cert.isSelfSigned()) {
|
|
QStringList l = cert.issuerInfo(QSslCertificate::OrganizationalUnitName);
|
|
if (!l.empty()) {
|
|
QString ou = l[0];
|
|
if (ou != "" && ou == _ou_token) {
|
|
QWebEngineCertificateError &e = const_cast<QWebEngineCertificateError &>(certificateError);
|
|
e.acceptCertificate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WebviewWindow::processJsEvents()
|
|
{
|
|
QWebEnginePage *p = _view->page();
|
|
p->runJavaScript("if (window.rkt_get_events) { window.rkt_get_events(); } else { JSON.stringify([]); }",
|
|
[this](const QVariant &v) {
|
|
QString s = v.toString();
|
|
QJsonParseError err;
|
|
QJsonDocument doc(QJsonDocument::fromJson(s.toUtf8(), &err));
|
|
if (err.error == QJsonParseError::NoError) {
|
|
QJsonArray a = doc.array();
|
|
int i, N;
|
|
for(i = 0, N = a.size(); i < N; i++) {
|
|
QJsonObject js_evt = a[i].toObject();
|
|
|
|
EventContainer e("js-evt");
|
|
e["js-evt"] = js_evt;
|
|
|
|
this->_container->triggerEvent(_view->id(), e);
|
|
}
|
|
} else {
|
|
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
void WebviewWindow::closeEvent(QCloseEvent *evt)
|
|
{
|
|
if (_must_close) {
|
|
EventContainer e("closed");
|
|
_container->triggerEvent(_view->id(), e);
|
|
_container->removeView(_view->id());
|
|
_view->deleteLater();
|
|
this->deleteLater();
|
|
if (_devtools != nullptr) {
|
|
_devtools->close();
|
|
_devtools->deleteLater();
|
|
}
|
|
} else {
|
|
evt->ignore();
|
|
EventContainer e("can-close?");
|
|
_container->triggerEvent(_view->id(), e);
|
|
}
|
|
}
|
|
|
|
void WebviewWindow::closeView()
|
|
{
|
|
_must_close = true;
|
|
close();
|
|
}
|
|
|
|
bool WebviewWindow::windowCreated()
|
|
{
|
|
return _window_created;
|
|
}
|
|
|
|
int WebviewWindow::moveCount()
|
|
{
|
|
return _moved;
|
|
}
|
|
|
|
int WebviewWindow::resizeCount()
|
|
{
|
|
return _resized;
|
|
}
|
|
|
|
void WebviewWindow::setOUToken(const QString &token)
|
|
{
|
|
_ou_token = token;
|
|
}
|
|
|
|
bool WebviewWindow::navigationEventSent()
|
|
{
|
|
return _navigation_event_sent;
|
|
}
|
|
|
|
void WebviewWindow::addView(WebViewQt *v, Rktwebview_qt *c)
|
|
{
|
|
_container = c;
|
|
_view = v;
|
|
this->setCentralWidget(v);
|
|
|
|
QWebEnginePage *page = _view->page();
|
|
|
|
connect(page, &QWebEnginePage::loadFinished, this, [this](bool ok) {
|
|
_container->pageLoaded(_view->id(), ok);
|
|
});
|
|
connect(page, &QWebEnginePage::loadStarted, this, [this]() {
|
|
_container->onPageLoad(_view->id());
|
|
});
|
|
connect(page, &QWebEnginePage::navigationRequested, this, &WebviewWindow::navigationRequested);
|
|
|
|
connect(page, &QWebEnginePage::certificateError, this, &WebviewWindow::handleCertificate);
|
|
|
|
connect(page, &QWebEnginePage::windowCloseRequested, this, &WebviewWindow::closeView);
|
|
|
|
connect(page, &QWebEnginePage::linkHovered, this, &WebviewWindow::linkHovered);
|
|
|
|
connect(page, &QWebEnginePage::printRequestedByFrame, this, &WebviewWindow::evtRequested);
|
|
}
|
|
|
|
WebViewQt *WebviewWindow::view()
|
|
{
|
|
return _view;
|
|
}
|
|
|
|
void WebviewWindow::runJs(const QString &js)
|
|
{
|
|
QWebEnginePage *p = _view->page();
|
|
p->runJavaScript(js);
|
|
}
|
|
|
|
void WebviewWindow::callJs(const QString &js, Command *c)
|
|
{
|
|
QWebEnginePage *p = _view->page();
|
|
QString _js = QString("{\n") +
|
|
" let f = function() {\n" +
|
|
" " + js + "\n" +
|
|
" };\n" +
|
|
" try {\n" +
|
|
" let obj = { oke: true, result: f(), exn: false };\n" +
|
|
" obj;\n" +
|
|
" } catch(e) {\n" +
|
|
" let obj = { oke: false, result: false, exn: e.message };\n" +
|
|
" obj;\n" +
|
|
" }\n" +
|
|
"}";
|
|
p->runJavaScript(_js, [c](const QVariant &v) {
|
|
c->result = v;
|
|
QJsonObject obj = v.toJsonObject();
|
|
bool ok = obj["oke"].toBool();
|
|
c->js_result_ok = ok;
|
|
c->result = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Compact));
|
|
c->done = true;
|
|
});
|
|
}
|
|
|
|
void WebviewWindow::openDevTools()
|
|
{
|
|
_devtools = new QMainWindow(this);
|
|
QWebEngineView *devtools_view = new QWebEngineView(_devtools);
|
|
_devtools->setCentralWidget(devtools_view);
|
|
_devtools->resize(800, 600);
|
|
_devtools->show();
|
|
_view->page()->setDevToolsPage(devtools_view->page());
|
|
connect(_devtools, &WebviewWindow::destroyed, this, [this](QObject *) {
|
|
_devtools = nullptr;
|
|
});
|
|
}
|
|
|
|
void WebviewWindow::linkHovered(const QUrl &u)
|
|
{
|
|
QString s = u.toString();
|
|
EventContainer hover_event("link-hovered");
|
|
hover_event["url"] = s;
|
|
_container->triggerEvent(_view->id(), hover_event);
|
|
}
|
|
|
|
void WebviewWindow::evtRequested(QWebEngineFrame frame)
|
|
{
|
|
if (frame.name() == "rkt-evt-frame") {
|
|
processJsEvents();
|
|
}
|
|
}
|
|
|
|
|
|
void WebviewWindow::moveEvent(QMoveEvent *event)
|
|
{
|
|
_x = event->pos().x();
|
|
_y = event->pos().y();
|
|
_move_timer.setSingleShot(true);
|
|
_move_timer.start(500);
|
|
_moved += 1;
|
|
//triggerMove();
|
|
}
|
|
|
|
void WebviewWindow::triggerMove()
|
|
{
|
|
EventContainer xy("move");
|
|
xy["x"] = _x;
|
|
xy["y"] = _y;
|
|
_container->triggerEvent(_view->id(), xy);
|
|
}
|
|
|
|
QWebEngineProfile *WebviewWindow::profile()
|
|
{
|
|
return _profile;
|
|
}
|
|
|
|
void WebviewWindow::resizeEvent(QResizeEvent *event)
|
|
{
|
|
_w = event->size().width();
|
|
_h = event->size().height();
|
|
_resize_timer.setSingleShot(true);
|
|
_resize_timer.start(500);
|
|
_resized += 1;
|
|
//triggerResize();
|
|
}
|
|
|
|
void WebviewWindow::triggerResize()
|
|
{
|
|
EventContainer s("resize");
|
|
s["w"] = _w;
|
|
s["h"] = _h;
|
|
_container->triggerEvent(_view->id(), s);
|
|
}
|
|
|
|
void WebviewWindow::showEvent(QShowEvent *event)
|
|
{
|
|
_window_created = true;
|
|
|
|
EventContainer show("show");
|
|
_container->triggerEvent(_view->id(), show);
|
|
}
|
|
|
|
void WebviewWindow::hideEvent(QHideEvent *event)
|
|
{
|
|
if (!_must_close) {
|
|
EventContainer hide("hide");
|
|
_container->triggerEvent(_view->id(), hide);
|
|
}
|
|
}
|
|
|
|
|