diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-04-13 19:29:37 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-04-13 19:29:37 +0200 |
commit | 899ca952964a09bf2c2304b42d2ce0d859c99c39 (patch) | |
tree | 96bf473799500f91e02081521c44eaef1eca01a5 | |
parent | cceb07e1ce6c161ad92d98b3922956c4a99e52db (diff) | |
download | kube-899ca952964a09bf2c2304b42d2ce0d859c99c39.tar.gz kube-899ca952964a09bf2c2304b42d2ce0d859c99c39.zip |
Ported away from webkit and to webengine
-rw-r--r-- | dist/kube.spec | 3 | ||||
-rw-r--r-- | framework/src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | framework/src/domain/composercontroller.cpp | 7 | ||||
-rw-r--r-- | framework/src/domain/mailtemplates.cpp | 169 | ||||
-rw-r--r-- | 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 @@ | |||
1 | Name: kube | 1 | Name: kube |
2 | Version: 0.2 | 2 | Version: 0.2 |
3 | Release: 3%{?dist} | 3 | Release: 4%{?dist} |
4 | Summary: kube | 4 | Summary: kube |
5 | 5 | ||
6 | Group: Applications/Desktop | 6 | Group: Applications/Desktop |
@@ -20,7 +20,6 @@ BuildRequires: kf5-messagelib-devel | |||
20 | BuildRequires: lmdb-devel | 20 | BuildRequires: lmdb-devel |
21 | BuildRequires: qt5-qtbase-devel | 21 | BuildRequires: qt5-qtbase-devel |
22 | BuildRequires: qt5-qtdeclarative-devel | 22 | BuildRequires: qt5-qtdeclarative-devel |
23 | BuildRequires: qt5-qtwebkit-devel | ||
24 | BuildRequires: qt5-qtwebengine-devel | 23 | BuildRequires: qt5-qtwebengine-devel |
25 | BuildRequires: sink-devel | 24 | BuildRequires: sink-devel |
26 | BuildRequires: libcurl-devel | 25 | 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 | |||
52 | ) | 52 | ) |
53 | 53 | ||
54 | add_library(frameworkplugin SHARED ${SRCS}) | 54 | add_library(frameworkplugin SHARED ${SRCS}) |
55 | qt5_use_modules(frameworkplugin Core Quick Qml WebKitWidgets Test) | 55 | qt5_use_modules(frameworkplugin Core Quick Qml WebEngineWidgets Test) |
56 | target_link_libraries(frameworkplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KAsync) | 56 | target_link_libraries(frameworkplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KAsync) |
57 | install(TARGETS frameworkplugin DESTINATION ${FRAMEWORK_INSTALL_DIR}) | 57 | install(TARGETS frameworkplugin DESTINATION ${FRAMEWORK_INSTALL_DIR}) |
58 | 58 | ||
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) | |||
149 | if (loadAsDraft) { | 149 | if (loadAsDraft) { |
150 | setMessage(mail); | 150 | setMessage(mail); |
151 | } else { | 151 | } else { |
152 | auto reply = MailTemplates::reply(mail); | 152 | MailTemplates::reply(mail, [this] (const KMime::Message::Ptr &reply) { |
153 | //We assume reply | 153 | //We assume reply |
154 | setMessage(reply); | 154 | setMessage(reply); |
155 | }); | ||
155 | } | 156 | } |
156 | } else { | 157 | } else { |
157 | qWarning() << "Retrieved empty message"; | 158 | 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 @@ | |||
20 | */ | 20 | */ |
21 | #include "mailtemplates.h" | 21 | #include "mailtemplates.h" |
22 | 22 | ||
23 | #include <functional> | ||
23 | #include <QByteArray> | 24 | #include <QByteArray> |
24 | #include <QList> | 25 | #include <QList> |
25 | #include <QDebug> | 26 | #include <QDebug> |
26 | #include <QImage> | 27 | #include <QWebEnginePage> |
27 | #include <QWebPage> | 28 | #include <QWebEngineProfile> |
28 | #include <QWebFrame> | 29 | #include <QWebEngineSettings> |
30 | #include <QWebEngineScript> | ||
29 | #include <QSysInfo> | 31 | #include <QSysInfo> |
30 | #include <QTextCodec> | 32 | #include <QTextCodec> |
31 | #include <QApplication> | ||
32 | 33 | ||
33 | #include <KCodecs/KCharsets> | 34 | #include <KCodecs/KCharsets> |
34 | #include <KMime/Types> | 35 | #include <KMime/Types> |
@@ -279,6 +280,7 @@ void makeValidHtml(QString &body, const QString &headElement) | |||
279 | } | 280 | } |
280 | } | 281 | } |
281 | 282 | ||
283 | //FIXME strip signature works partially for HTML mails | ||
282 | QString stripSignature(const QString &msg) | 284 | QString stripSignature(const QString &msg) |
283 | { | 285 | { |
284 | // Following RFC 3676, only > before -- | 286 | // Following RFC 3676, only > before -- |
@@ -340,65 +342,96 @@ QString stripSignature(const QString &msg) | |||
340 | return res; | 342 | return res; |
341 | } | 343 | } |
342 | 344 | ||
343 | QString plainMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature) | 345 | void setupPage(QWebEnginePage *page) |
344 | { | 346 | { |
345 | QString result = otp.plainTextContent(); | 347 | page->profile()->setHttpCacheType(QWebEngineProfile::MemoryHttpCache); |
346 | if (result.isEmpty()) { //HTML-only mails | 348 | page->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); |
347 | QWebPage doc; | 349 | page->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false); |
348 | doc.mainFrame()->setHtml(otp.htmlContent()); | 350 | page->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false); |
349 | result = doc.mainFrame()->toPlainText(); | 351 | page->settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false); |
352 | page->settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, false); | ||
353 | page->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); | ||
354 | page->settings()->setAttribute(QWebEngineSettings::XSSAuditingEnabled, false); | ||
355 | page->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); | ||
356 | page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false); | ||
357 | page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false); | ||
358 | page->settings()->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled, false); | ||
359 | page->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, false); | ||
360 | page->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false); | ||
361 | page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); | ||
362 | page->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false); | ||
363 | page->settings()->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, false); | ||
364 | page->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false); | ||
365 | |||
366 | #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) | ||
367 | page->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); | ||
368 | page->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, false); | ||
369 | #endif | ||
370 | } | ||
371 | |||
372 | void plainMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function<void(const QString &)> &callback) | ||
373 | { | ||
374 | QString result = plainTextContent; | ||
375 | if (plainTextContent.isEmpty()) { //HTML-only mails | ||
376 | auto page = new QWebEnginePage; | ||
377 | setupPage(page); | ||
378 | page->setHtml(htmlContent); | ||
379 | page->toPlainText([=] (const QString &plaintext) { | ||
380 | page->deleteLater(); | ||
381 | callback(plaintext); | ||
382 | }); | ||
383 | return; | ||
350 | } | 384 | } |
351 | 385 | ||
352 | if (aStripSignature) { | 386 | if (aStripSignature) { |
353 | result = stripSignature(result); | 387 | result = stripSignature(result); |
354 | } | 388 | } |
389 | callback(result); | ||
390 | } | ||
355 | 391 | ||
356 | return result; | 392 | QString extractHeaderBodyScript() |
393 | { | ||
394 | const QString source = QStringLiteral("(function() {" | ||
395 | "var res = {" | ||
396 | " body: document.getElementsByTagName('body')[0].innerHTML," | ||
397 | " header: document.getElementsByTagName('head')[0].innerHTML" | ||
398 | "};" | ||
399 | "return res;" | ||
400 | "})()"); | ||
401 | return source; | ||
357 | } | 402 | } |
358 | 403 | ||
359 | QString htmlMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature, QString &headElement) | 404 | void htmlMessageText(const QString &plainTextContent, const QString &htmlContent, bool aStripSignature, const std::function<void(const QString &body, QString &head)> &callback) |
360 | { | 405 | { |
361 | QString htmlElement = otp.htmlContent(); | 406 | QString htmlElement = htmlContent; |
362 | 407 | ||
363 | if (htmlElement.isEmpty()) { //plain mails only | 408 | if (htmlElement.isEmpty()) { //plain mails only |
364 | QString htmlReplace = otp.plainTextContent().toHtmlEscaped(); | 409 | QString htmlReplace = plainTextContent.toHtmlEscaped(); |
365 | htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("<br />")); | 410 | htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("<br />")); |
366 | htmlElement = QStringLiteral("<html><head></head><body>%1</body></html>\n").arg(htmlReplace); | 411 | htmlElement = QStringLiteral("<html><head></head><body>%1</body></html>\n").arg(htmlReplace); |
367 | } | 412 | } |
368 | 413 | ||
369 | //QWebPage relies on this | 414 | auto page = new QWebEnginePage; |
370 | Q_ASSERT(QApplication::style()); | 415 | setupPage(page); |
371 | QWebPage page; | 416 | |
372 | page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); | 417 | page->setHtml(htmlElement); |
373 | page.settings()->setAttribute(QWebSettings::JavaEnabled, false); | 418 | page->runJavaScript(extractHeaderBodyScript(), QWebEngineScript::ApplicationWorld, [=](const QVariant &result){ |
374 | page.settings()->setAttribute(QWebSettings::PluginsEnabled, false); | 419 | page->deleteLater(); |
375 | page.settings()->setAttribute(QWebSettings::AutoLoadImages, false); | 420 | const QVariantMap map = result.toMap(); |
376 | 421 | auto bodyElement = map.value(QStringLiteral("body")).toString(); | |
377 | page.currentFrame()->setHtml(htmlElement); | 422 | auto headerElement = map.value(QStringLiteral("header")).toString(); |
378 | 423 | if (!bodyElement.isEmpty()) { | |
379 | //TODO to be tested/verified if this is not an issue | 424 | if (aStripSignature) { |
380 | page.settings()->setAttribute(QWebSettings::JavascriptEnabled, true); | 425 | callback(stripSignature(bodyElement), headerElement); |
381 | const QString bodyElement = page.currentFrame()->evaluateJavaScript( | 426 | } |
382 | QStringLiteral("document.getElementsByTagName('body')[0].innerHTML")).toString(); | 427 | return callback(bodyElement, headerElement); |
383 | 428 | } | |
384 | headElement = page.currentFrame()->evaluateJavaScript( | ||
385 | QStringLiteral("document.getElementsByTagName('head')[0].innerHTML")).toString(); | ||
386 | |||
387 | page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); | ||
388 | 429 | ||
389 | if (!bodyElement.isEmpty()) { | ||
390 | if (aStripSignature) { | 430 | if (aStripSignature) { |
391 | //FIXME strip signature works partially for HTML mails | 431 | return callback(stripSignature(htmlElement), headerElement); |
392 | return stripSignature(bodyElement); | ||
393 | } | 432 | } |
394 | return bodyElement; | 433 | return callback(htmlElement, headerElement); |
395 | } | 434 | }); |
396 | |||
397 | if (aStripSignature) { | ||
398 | //FIXME strip signature works partially for HTML mails | ||
399 | return stripSignature(htmlElement); | ||
400 | } | ||
401 | return htmlElement; | ||
402 | } | 435 | } |
403 | 436 | ||
404 | QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) | 437 | QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) |
@@ -536,7 +569,7 @@ enum ReplyStrategy { | |||
536 | ReplyNone | 569 | ReplyNone |
537 | }; | 570 | }; |
538 | 571 | ||
539 | KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) | 572 | void MailTemplates::reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback) |
540 | { | 573 | { |
541 | //FIXME | 574 | //FIXME |
542 | const bool alwaysPlain = true; | 575 | const bool alwaysPlain = true; |
@@ -776,26 +809,32 @@ KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) | |||
776 | //Strip signature for replies | 809 | //Strip signature for replies |
777 | const bool stripSignature = true; | 810 | const bool stripSignature = true; |
778 | 811 | ||
779 | //Quoted body | 812 | const auto plainTextContent = otp.plainTextContent(); |
780 | QString plainQuote = quotedPlainText(plainMessageText(otp, stripSignature), origMsg->from()->displayString()); | 813 | const auto htmlContent = otp.htmlContent(); |
781 | if (plainQuote.endsWith(QLatin1Char('\n'))) { | ||
782 | plainQuote.chop(1); | ||
783 | } | ||
784 | plainBody.append(plainQuote); | ||
785 | QString headElement; | ||
786 | htmlBody.append(quotedHtmlText(htmlMessageText(otp, stripSignature, headElement))); | ||
787 | |||
788 | if (alwaysPlain) { | ||
789 | htmlBody.clear(); | ||
790 | } else { | ||
791 | makeValidHtml(htmlBody, headElement); | ||
792 | } | ||
793 | 814 | ||
794 | addProcessedBodyToMessage(msg, plainBody, htmlBody, false); | 815 | plainMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body) { |
795 | 816 | //Quoted body | |
796 | applyCharset(msg, origMsg); | 817 | QString plainQuote = quotedPlainText(body, origMsg->from()->displayString()); |
797 | 818 | if (plainQuote.endsWith(QLatin1Char('\n'))) { | |
798 | msg->assemble(); | 819 | plainQuote.chop(1); |
820 | } | ||
821 | //The plain body is complete | ||
822 | auto plainBodyResult = plainBody + plainQuote; | ||
823 | htmlMessageText(plainTextContent, htmlContent, stripSignature, [=] (const QString &body, const QString &headElement) { | ||
824 | //The html body is complete | ||
825 | auto htmlBodyResult = htmlBody + quotedHtmlText(body); | ||
826 | if (alwaysPlain) { | ||
827 | htmlBodyResult.clear(); | ||
828 | } else { | ||
829 | makeValidHtml(htmlBodyResult, headElement); | ||
830 | } | ||
799 | 831 | ||
800 | return msg; | 832 | //Assemble the message |
833 | addProcessedBodyToMessage(msg, plainBodyResult, htmlBodyResult, false); | ||
834 | applyCharset(msg, origMsg); | ||
835 | msg->assemble(); | ||
836 | //We're done | ||
837 | callback(msg); | ||
838 | }); | ||
839 | }); | ||
801 | } | 840 | } |
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 @@ | |||
21 | 21 | ||
22 | #include <QByteArray> | 22 | #include <QByteArray> |
23 | #include <KMime/Message> | 23 | #include <KMime/Message> |
24 | #include <functional> | ||
24 | 25 | ||
25 | namespace MailTemplates | 26 | namespace MailTemplates |
26 | { | 27 | { |
27 | KMime::Message::Ptr reply(const KMime::Message::Ptr &message); | 28 | void reply(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); |
28 | }; | 29 | }; |