summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-13 19:29:37 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-13 19:29:37 +0200
commit899ca952964a09bf2c2304b42d2ce0d859c99c39 (patch)
tree96bf473799500f91e02081521c44eaef1eca01a5
parentcceb07e1ce6c161ad92d98b3922956c4a99e52db (diff)
downloadkube-899ca952964a09bf2c2304b42d2ce0d859c99c39.tar.gz
kube-899ca952964a09bf2c2304b42d2ce0d859c99c39.zip
Ported away from webkit and to webengine
-rw-r--r--dist/kube.spec3
-rw-r--r--framework/src/CMakeLists.txt2
-rw-r--r--framework/src/domain/composercontroller.cpp7
-rw-r--r--framework/src/domain/mailtemplates.cpp169
-rw-r--r--framework/src/domain/mailtemplates.h3
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 @@
1Name: kube 1Name: kube
2Version: 0.2 2Version: 0.2
3Release: 3%{?dist} 3Release: 4%{?dist}
4Summary: kube 4Summary: kube
5 5
6Group: Applications/Desktop 6Group: Applications/Desktop
@@ -20,7 +20,6 @@ BuildRequires: kf5-messagelib-devel
20BuildRequires: lmdb-devel 20BuildRequires: lmdb-devel
21BuildRequires: qt5-qtbase-devel 21BuildRequires: qt5-qtbase-devel
22BuildRequires: qt5-qtdeclarative-devel 22BuildRequires: qt5-qtdeclarative-devel
23BuildRequires: qt5-qtwebkit-devel
24BuildRequires: qt5-qtwebengine-devel 23BuildRequires: qt5-qtwebengine-devel
25BuildRequires: sink-devel 24BuildRequires: sink-devel
26BuildRequires: libcurl-devel 25BuildRequires: 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
54add_library(frameworkplugin SHARED ${SRCS}) 54add_library(frameworkplugin SHARED ${SRCS})
55qt5_use_modules(frameworkplugin Core Quick Qml WebKitWidgets Test) 55qt5_use_modules(frameworkplugin Core Quick Qml WebEngineWidgets Test)
56target_link_libraries(frameworkplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KAsync) 56target_link_libraries(frameworkplugin sink mimetreeparser KF5::MimeTreeParser KF5::Codecs KF5::Package KAsync)
57install(TARGETS frameworkplugin DESTINATION ${FRAMEWORK_INSTALL_DIR}) 57install(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
282QString stripSignature(const QString &msg) 284QString 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
343QString plainMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature) 345void 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
372void 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; 392QString 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
359QString htmlMessageText(MimeTreeParser::ObjectTreeParser &otp, bool aStripSignature, QString &headElement) 404void 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
404QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) 437QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString)
@@ -536,7 +569,7 @@ enum ReplyStrategy {
536 ReplyNone 569 ReplyNone
537}; 570};
538 571
539KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) 572void 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
25namespace MailTemplates 26namespace 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};