From 899ca952964a09bf2c2304b42d2ce0d859c99c39 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 13 Apr 2017 19:29:37 +0200 Subject: Ported away from webkit and to webengine --- dist/kube.spec | 3 +- framework/src/CMakeLists.txt | 2 +- framework/src/domain/composercontroller.cpp | 7 +- framework/src/domain/mailtemplates.cpp | 169 +++++++++++++++++----------- framework/src/domain/mailtemplates.h | 3 +- 5 files changed, 112 insertions(+), 72 deletions(-) diff --git a/dist/kube.spec b/dist/kube.spec index 223f379d..5450aea1 100644 --- a/dist/kube.spec +++ b/dist/kube.spec @@ -1,6 +1,6 @@ Name: kube Version: 0.2 -Release: 3%{?dist} +Release: 4%{?dist} Summary: kube Group: Applications/Desktop @@ -20,7 +20,6 @@ BuildRequires: kf5-messagelib-devel BuildRequires: lmdb-devel BuildRequires: qt5-qtbase-devel BuildRequires: qt5-qtdeclarative-devel -BuildRequires: qt5-qtwebkit-devel BuildRequires: qt5-qtwebengine-devel BuildRequires: sink-devel BuildRequires: libcurl-devel diff --git a/framework/src/CMakeLists.txt b/framework/src/CMakeLists.txt index f7902aa7..b773748b 100644 --- a/framework/src/CMakeLists.txt +++ b/framework/src/CMakeLists.txt @@ -52,7 +52,7 @@ set(SRCS ) add_library(frameworkplugin SHARED ${SRCS}) -qt5_use_modules(frameworkplugin Core Quick Qml WebKitWidgets Test) +qt5_use_modules(frameworkplugin Core Quick Qml WebEngineWidgets Test) target_link_libraries(frameworkplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KAsync) install(TARGETS frameworkplugin DESTINATION ${FRAMEWORK_INSTALL_DIR}) diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp index 3328d9eb..ef77d714 100644 --- a/framework/src/domain/composercontroller.cpp +++ b/framework/src/domain/composercontroller.cpp @@ -149,9 +149,10 @@ void ComposerController::loadMessage(const QVariant &message, bool loadAsDraft) if (loadAsDraft) { setMessage(mail); } else { - auto reply = MailTemplates::reply(mail); - //We assume reply - setMessage(reply); + MailTemplates::reply(mail, [this] (const KMime::Message::Ptr &reply) { + //We assume reply + setMessage(reply); + }); } } else { qWarning() << "Retrieved empty message"; diff --git a/framework/src/domain/mailtemplates.cpp b/framework/src/domain/mailtemplates.cpp index 6af381d2..43e169de 100644 --- a/framework/src/domain/mailtemplates.cpp +++ b/framework/src/domain/mailtemplates.cpp @@ -20,15 +20,16 @@ */ #include "mailtemplates.h" +#include #include #include #include -#include -#include -#include +#include +#include +#include +#include #include #include -#include #include #include @@ -279,6 +280,7 @@ void makeValidHtml(QString &body, const QString &headElement) } } +//FIXME strip signature works partially for HTML mails QString stripSignature(const QString &msg) { // Following RFC 3676, only > before -- @@ -340,65 +342,96 @@ QString stripSignature(const QString &msg) return res; } -QString plainMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature) +void setupPage(QWebEnginePage *page) { - QString result = otp.plainTextContent(); - if (result.isEmpty()) { //HTML-only mails - QWebPage doc; - doc.mainFrame()->setHtml(otp.htmlContent()); - result = doc.mainFrame()->toPlainText(); + page->profile()->setHttpCacheType(QWebEngineProfile::MemoryHttpCache); + page->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); + page->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false); + page->settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, false); + page->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::XSSAuditingEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false); + page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false); + page->settings()->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false); + page->settings()->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + page->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); + page->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, false); +#endif +} + +void plainMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function &callback) +{ + QString result = plainTextContent; + if (plainTextContent.isEmpty()) { //HTML-only mails + auto page = new QWebEnginePage; + setupPage(page); + page->setHtml(htmlContent); + page->toPlainText([=] (const QString &plaintext) { + page->deleteLater(); + callback(plaintext); + }); + return; } if (aStripSignature) { result = stripSignature(result); } + callback(result); +} - return result; +QString extractHeaderBodyScript() +{ + const QString source = QStringLiteral("(function() {" + "var res = {" + " body: document.getElementsByTagName('body')[0].innerHTML," + " header: document.getElementsByTagName('head')[0].innerHTML" + "};" + "return res;" + "})()"); + return source; } -QString htmlMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature, QString &headElement) +void htmlMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function &callback) { - QString htmlElement = otp.htmlContent(); + QString htmlElement = htmlContent; if (htmlElement.isEmpty()) { //plain mails only - QString htmlReplace = otp.plainTextContent().toHtmlEscaped(); + QString htmlReplace = plainTextContent.toHtmlEscaped(); htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("
")); htmlElement = QStringLiteral("%1\n").arg(htmlReplace); } - //QWebPage relies on this - Q_ASSERT(QApplication::style()); - QWebPage page; - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); - page.settings()->setAttribute(QWebSettings::JavaEnabled, false); - page.settings()->setAttribute(QWebSettings::PluginsEnabled, false); - page.settings()->setAttribute(QWebSettings::AutoLoadImages, false); - - page.currentFrame()->setHtml(htmlElement); - - //TODO to be tested/verified if this is not an issue - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, true); - const QString bodyElement = page.currentFrame()->evaluateJavaScript( - QStringLiteral("document.getElementsByTagName('body')[0].innerHTML")).toString(); - - headElement = page.currentFrame()->evaluateJavaScript( - QStringLiteral("document.getElementsByTagName('head')[0].innerHTML")).toString(); - - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); + auto page = new QWebEnginePage; + setupPage(page); + + page->setHtml(htmlElement); + page->runJavaScript(extractHeaderBodyScript(), QWebEngineScript::ApplicationWorld, [=](const QVariant &result){ + page->deleteLater(); + const QVariantMap map = result.toMap(); + auto bodyElement = map.value(QStringLiteral("body")).toString(); + auto headerElement = map.value(QStringLiteral("header")).toString(); + if (!bodyElement.isEmpty()) { + if (aStripSignature) { + callback(stripSignature(bodyElement), headerElement); + } + return callback(bodyElement, headerElement); + } - if (!bodyElement.isEmpty()) { if (aStripSignature) { - //FIXME strip signature works partially for HTML mails - return stripSignature(bodyElement); + return callback(stripSignature(htmlElement), headerElement); } - return bodyElement; - } - - if (aStripSignature) { - //FIXME strip signature works partially for HTML mails - return stripSignature(htmlElement); - } - return htmlElement; + return callback(htmlElement, headerElement); + }); } QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) @@ -536,7 +569,7 @@ enum ReplyStrategy { ReplyNone }; -KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) +void MailTemplates::reply(const KMime::Message::Ptr &origMsg, const std::function &callback) { //FIXME const bool alwaysPlain = true; @@ -776,26 +809,32 @@ KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) //Strip signature for replies const bool stripSignature = true; - //Quoted body - QString plainQuote = quotedPlainText(plainMessageText(otp, stripSignature), origMsg->from()->displayString()); - if (plainQuote.endsWith(QLatin1Char('\n'))) { - plainQuote.chop(1); - } - plainBody.append(plainQuote); - QString headElement; - htmlBody.append(quotedHtmlText(htmlMessageText(otp, stripSignature, headElement))); - - if (alwaysPlain) { - htmlBody.clear(); - } else { - makeValidHtml(htmlBody, headElement); - } + const auto plainTextContent = otp.plainTextContent(); + const auto htmlContent = otp.htmlContent(); - addProcessedBodyToMessage(msg, plainBody, htmlBody, false); - - applyCharset(msg, origMsg); - - msg->assemble(); + plainMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body) { + //Quoted body + QString plainQuote = quotedPlainText(body, origMsg->from()->displayString()); + if (plainQuote.endsWith(QLatin1Char('\n'))) { + plainQuote.chop(1); + } + //The plain body is complete + auto plainBodyResult = plainBody + plainQuote; + htmlMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body, const QString &headElement) { + //The html body is complete + auto htmlBodyResult = htmlBody + quotedHtmlText(body); + if (alwaysPlain) { + htmlBodyResult.clear(); + } else { + makeValidHtml(htmlBodyResult, headElement); + } - return msg; + //Assemble the message + addProcessedBodyToMessage(msg, plainBodyResult, htmlBodyResult, false); + applyCharset(msg, origMsg); + msg->assemble(); + //We're done + callback(msg); + }); + }); } diff --git a/framework/src/domain/mailtemplates.h b/framework/src/domain/mailtemplates.h index 6519122a..db269c96 100644 --- a/framework/src/domain/mailtemplates.h +++ b/framework/src/domain/mailtemplates.h @@ -21,8 +21,9 @@ #include #include +#include namespace MailTemplates { - KMime::Message::Ptr reply(const KMime::Message::Ptr &message); + void reply(const KMime::Message::Ptr &origMsg, const std::function &callback); }; -- cgit v1.2.3