mailwebengineview.cpp 11.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
  Copyright (c) 2016 Montel Laurent <montel@kde.org>

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

Laurent Montel's avatar
Laurent Montel committed
18
#include "mailwebengineview.h"
Laurent Montel's avatar
Laurent Montel committed
19
#include "mailwebenginepage.h"
Laurent Montel's avatar
Laurent Montel committed
20
21
#include "webengineviewer/webengineaccesskey.h"
#include "webengineviewer/webenginescript.h"
Laurent Montel's avatar
Laurent Montel committed
22
#include "mailwebenginescript.h"
23
#include "messageviewer/messageviewersettings.h"
24
25
#include "loadexternalreferencesurlinterceptor/loadexternalreferencesurlinterceptor.h"
#include "cidreferencesurlinterceptor/cidreferencesurlinterceptor.h"
Laurent Montel's avatar
Laurent Montel committed
26
#include <WebEngineViewer/NetworkAccessManagerWebEngine>
Laurent Montel's avatar
Laurent Montel committed
27

Laurent Montel's avatar
Laurent Montel committed
28
#include "scamdetection/scamdetectionwebengine.h"
Laurent Montel's avatar
Laurent Montel committed
29
#include "scamdetection/scamcheckshorturl.h"
Laurent Montel's avatar
Laurent Montel committed
30
#include <QContextMenuEvent>
Laurent Montel's avatar
Laurent Montel committed
31
#include <WebEngineViewer/WebHitTest>
Laurent Montel's avatar
Laurent Montel committed
32

Laurent Montel's avatar
Improve    
Laurent Montel committed
33
#include <QWebEngineSettings>
34
#include <QWebEngineProfile>
Laurent Montel's avatar
Improve    
Laurent Montel committed
35

Laurent Montel's avatar
Laurent Montel committed
36
37
#include <WebEngineViewer/WebHitTestResult>

38
using namespace MessageViewer;
Laurent Montel's avatar
Laurent Montel committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
template<typename Arg, typename R, typename C>
struct InvokeWrapper {
    R *receiver;
    void (C::*memberFunction)(Arg);
    void operator()(Arg result)
    {
        (receiver->*memberFunction)(result);
    }
};

template<typename Arg, typename R, typename C>

InvokeWrapper<Arg, R, C> invoke(R *receiver, void (C::*memberFunction)(Arg))
{
    InvokeWrapper<Arg, R, C> wrapper = {receiver, memberFunction};
    return wrapper;
}
56

Laurent Montel's avatar
Laurent Montel committed
57
58
59
60
class MessageViewer::MailWebEngineViewPrivate
{
public:
    MailWebEngineViewPrivate()
61
62
        : mScamDetection(Q_NULLPTR),
          mWebViewAccessKey(Q_NULLPTR),
Laurent Montel's avatar
Laurent Montel committed
63
          mExternalReference(Q_NULLPTR),
64
65
          mPageEngine(Q_NULLPTR),
          mNetworkAccessManager(Q_NULLPTR)
Laurent Montel's avatar
Laurent Montel committed
66
67
68
    {

    }
Laurent Montel's avatar
Laurent Montel committed
69
    ScamDetectionWebEngine *mScamDetection;
Laurent Montel's avatar
Laurent Montel committed
70
    WebEngineViewer::WebEngineAccessKey *mWebViewAccessKey;
71
    MessageViewer::LoadExternalReferencesUrlInterceptor *mExternalReference;
Laurent Montel's avatar
Laurent Montel committed
72
    MailWebEnginePage *mPageEngine;
Laurent Montel's avatar
Laurent Montel committed
73
    WebEngineViewer::NetworkAccessManagerWebEngine *mNetworkAccessManager;
Laurent Montel's avatar
Laurent Montel committed
74
75
};

Laurent Montel's avatar
Laurent Montel committed
76
MailWebEngineView::MailWebEngineView(KActionCollection *ac, QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
77
    : WebEngineViewer::WebEngineView(parent),
Laurent Montel's avatar
Laurent Montel committed
78
79
      d(new MessageViewer::MailWebEngineViewPrivate)

80
{
Laurent Montel's avatar
Improve    
Laurent Montel committed
81
    settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
Laurent Montel's avatar
Laurent Montel committed
82
    d->mWebViewAccessKey = new WebEngineViewer::WebEngineAccessKey(this, this);
Laurent Montel's avatar
Laurent Montel committed
83
    d->mWebViewAccessKey->setActionCollection(ac);
Laurent Montel's avatar
Laurent Montel committed
84
    d->mScamDetection = new ScamDetectionWebEngine(this);
85
    connect(d->mScamDetection, &ScamDetectionWebEngine::messageMayBeAScam, this, &MailWebEngineView::messageMayBeAScam);
Laurent Montel's avatar
Laurent Montel committed
86
    connect(d->mWebViewAccessKey, &WebEngineViewer::WebEngineAccessKey::openUrl, this, &MailWebEngineView::openUrl);
Laurent Montel's avatar
Laurent Montel committed
87
    connect(this, &MailWebEngineView::loadFinished, this, &MailWebEngineView::slotLoadFinished);
88

Laurent Montel's avatar
Laurent Montel committed
89
    d->mNetworkAccessManager = new WebEngineViewer::NetworkAccessManagerWebEngine(this, ac, this);
90
    d->mExternalReference = new MessageViewer::LoadExternalReferencesUrlInterceptor(this);
91
    d->mNetworkAccessManager->addInterceptor(d->mExternalReference);
Laurent Montel's avatar
Laurent Montel committed
92
93
    MessageViewer::CidReferencesUrlInterceptor *cidReference = new MessageViewer::CidReferencesUrlInterceptor(this);
    d->mNetworkAccessManager->addInterceptor(cidReference);
Laurent Montel's avatar
Laurent Montel committed
94
95
    d->mPageEngine = new MailWebEnginePage(this);
    setPage(d->mPageEngine);
96
    QWebEngineProfile::defaultProfile()->setHttpCacheType(QWebEngineProfile::MemoryHttpCache);
Laurent Montel's avatar
Laurent Montel committed
97
    setFocusPolicy(Qt::WheelFocus);
Laurent Montel's avatar
Laurent Montel committed
98
    connect(d->mPageEngine, &MailWebEnginePage::urlClicked, this, &MailWebEngineView::openUrl);
99
100
101
#if QT_VERSION >= 0x050700
    connect(page(), &QWebEnginePage::scrollPositionChanged, d->mWebViewAccessKey, &WebEngineViewer::WebEngineAccessKey::hideAccessKeys);
#endif
102
103
}

Laurent Montel's avatar
Laurent Montel committed
104
MailWebEngineView::~MailWebEngineView()
105
{
Laurent Montel's avatar
Laurent Montel committed
106
    delete d;
107
}
Laurent Montel's avatar
Laurent Montel committed
108

Laurent Montel's avatar
Laurent Montel committed
109
110
void MailWebEngineView::contextMenuEvent(QContextMenuEvent *e)
{
Laurent Montel's avatar
Laurent Montel committed
111
112
    WebEngineViewer::WebHitTest *webHit = d->mPageEngine->hitTestContent(e->pos());
    connect(webHit, &WebEngineViewer::WebHitTest::finished, this, &MailWebEngineView::slotWebHitFinished);
Laurent Montel's avatar
Laurent Montel committed
113
114
}

Laurent Montel's avatar
Laurent Montel committed
115
void MailWebEngineView::slotWebHitFinished(const WebEngineViewer::WebHitTestResult &result)
Laurent Montel's avatar
Laurent Montel committed
116
{
Laurent Montel's avatar
Laurent Montel committed
117
    Q_EMIT popupMenu(result);
Laurent Montel's avatar
Laurent Montel committed
118
119
}

Laurent Montel's avatar
Laurent Montel committed
120
121
void MailWebEngineView::scrollUp(int pixels)
{
Laurent Montel's avatar
Laurent Montel committed
122
    page()->runJavaScript(WebEngineViewer::WebEngineScript::scrollUp(pixels));
Laurent Montel's avatar
Laurent Montel committed
123
124
125
126
}

void MailWebEngineView::scrollDown(int pixels)
{
Laurent Montel's avatar
Laurent Montel committed
127
    page()->runJavaScript(WebEngineViewer::WebEngineScript::scrollDown(pixels));
Laurent Montel's avatar
Laurent Montel committed
128
129
}

Laurent Montel's avatar
Laurent Montel committed
130
131
132
133
void MailWebEngineView::selectAll()
{
    page()->triggerAction(QWebEnginePage::SelectAll);
}
Laurent Montel's avatar
Laurent Montel committed
134
135
136

void MailWebEngineView::slotZoomChanged(qreal zoom)
{
137
138
139
    qDebug() << " void MailWebEngineView::slotZoomChanged(qreal zoom)*******" << zoom;
    setZoomFactor(zoom*100);
    qDebug()<<" zoomFactor"<<zoomFactor();
Laurent Montel's avatar
Laurent Montel committed
140
141
}

Laurent Montel's avatar
Laurent Montel committed
142
143
144
145
146
void MailWebEngineView::scamCheck()
{
    d->mScamDetection->scanPage(page());
}

Laurent Montel's avatar
Laurent Montel committed
147
148
void MailWebEngineView::slotShowDetails()
{
Laurent Montel's avatar
Laurent Montel committed
149
    d->mScamDetection->showDetails();
Laurent Montel's avatar
Laurent Montel committed
150
}
151

Laurent Montel's avatar
Laurent Montel committed
152
void MailWebEngineView::forwardKeyReleaseEvent(QKeyEvent *e)
153
154
{
    if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
155
        d->mWebViewAccessKey->keyReleaseEvent(e);
156
157
158
    }
}

Laurent Montel's avatar
Laurent Montel committed
159
void MailWebEngineView::forwardKeyPressEvent(QKeyEvent *e)
160
161
162
{
    if (e && hasFocus()) {
        if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
163
            d->mWebViewAccessKey->keyPressEvent(e);
164
165
166
167
        }
    }
}

Laurent Montel's avatar
Laurent Montel committed
168
void MailWebEngineView::forwardWheelEvent(QWheelEvent *e)
169
170
{
    if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
171
        d->mWebViewAccessKey->wheelEvent(e);
172
173
174
175
176
177
    }
}

void MailWebEngineView::resizeEvent(QResizeEvent *e)
{
    if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
178
        d->mWebViewAccessKey->resizeEvent(e);
179
180
181
    }
    QWebEngineView::resizeEvent(e);
}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

void MailWebEngineView::saveMainFrameScreenshotInFile(const QString &filename)
{
    //TODO need to verify it
    QImage image(size(), QImage::Format_ARGB32_Premultiplied);
    image.fill(Qt::transparent);

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::TextAntialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    render(&painter);
    painter.end();
    image.save(filename);
}
Laurent Montel's avatar
Laurent Montel committed
197
198
199
200
201

void MailWebEngineView::showAccessKeys()
{
    d->mWebViewAccessKey->showAccessKeys();
}
Laurent Montel's avatar
Laurent Montel committed
202

Laurent Montel's avatar
Laurent Montel committed
203
204
bool MailWebEngineView::isScrolledToBottom() const
{
205
    qDebug() << "bool MailWebEngineView::isScrolledToBottom() const not implemented";
Laurent Montel's avatar
Laurent Montel committed
206
207
208
209
210
    //Convert as async
    //TODO '(window.innerHeight + window.scrollY) >= document.body.offsetHeight)'
    return false;
}

Laurent Montel's avatar
Laurent Montel committed
211
212
void MailWebEngineView::setElementByIdVisible(const QString &id, bool visible)
{
Laurent Montel's avatar
Laurent Montel committed
213
    page()->runJavaScript(WebEngineViewer::WebEngineScript::setElementByIdVisible(id, visible));
Laurent Montel's avatar
Laurent Montel committed
214
215
}

Laurent Montel's avatar
Laurent Montel committed
216
void MailWebEngineView::removeAttachmentMarking(const QString &id)
Laurent Montel's avatar
Laurent Montel committed
217
{
Laurent Montel's avatar
Laurent Montel committed
218
    page()->runJavaScript(WebEngineViewer::WebEngineScript::removeStyleToElement(QLatin1String("*#") + id));
Laurent Montel's avatar
Laurent Montel committed
219
220
221
222
223
}

void MailWebEngineView::markAttachment(const QString &id, const QString &style)
{
    //TODO verify "*#" + id
Laurent Montel's avatar
Laurent Montel committed
224
    page()->runJavaScript(WebEngineViewer::WebEngineScript::setStyleToElement(QLatin1String("*#") + id, style));
Laurent Montel's avatar
Laurent Montel committed
225
226
227
228
}

void MailWebEngineView::scrollToAnchor(const QString &anchor)
{
Laurent Montel's avatar
Laurent Montel committed
229
    page()->runJavaScript(WebEngineViewer::WebEngineScript::searchElementPosition(anchor), invoke(this, &MailWebEngineView::handleScrollToAnchor));
Laurent Montel's avatar
Laurent Montel committed
230
231
232
233
234
235
236
237
}

void MailWebEngineView::handleScrollToAnchor(const QVariant &result)
{
    if (result.isValid()) {
        const QList<QVariant> lst = result.toList();
        if (lst.count() == 2) {
            const QPoint pos(lst.at(0).toInt(), lst.at(1).toInt());
Laurent Montel's avatar
Laurent Montel committed
238
            page()->runJavaScript(WebEngineViewer::WebEngineScript::scrollToPosition(pos));
Laurent Montel's avatar
Laurent Montel committed
239
240
241
        }
    }
}
242
243
244

void MailWebEngineView::scrollPageDown(int percent)
{
Laurent Montel's avatar
Laurent Montel committed
245
    page()->runJavaScript(WebEngineViewer::WebEngineScript::scrollPercentage(percent));
246
247
248
249
250
251
}

void MailWebEngineView::scrollPageUp(int percent)
{
    scrollPageDown(-percent);
}
Laurent Montel's avatar
Laurent Montel committed
252
253
254

void MailWebEngineView::injectAttachments(const boost::function<QString()> &delayedHtml)
{
Laurent Montel's avatar
Laurent Montel committed
255
256
257
258
    const QString html = delayedHtml();
    if (html.isEmpty()) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
259
    page()->runJavaScript(MessageViewer::MailWebEngineScript::injectAttachments(html, QStringLiteral("attachmentInjectionPoint")));
Laurent Montel's avatar
Laurent Montel committed
260
261
}

262
void MailWebEngineView::toggleFullAddressList(const QString &field, const boost::function<QString()> &delayedHtml, bool doShow)
Laurent Montel's avatar
Laurent Montel committed
263
{
264
265
266
267
268
269
    const QString html = delayedHtml();
    if (html.isEmpty()) {
        return;
    }

    qDebug() << "void MailWebEngineView::toggleFullAddressList(const QString &field, const boost::function<QString()> &delayedHtml, bool doShow)" << html << " fields " << field;
Laurent Montel's avatar
Laurent Montel committed
270
    page()->runJavaScript(MessageViewer::MailWebEngineScript::replaceInnerHtml(field, html, doShow), invoke(this, &MailWebEngineView::updateToggleFullAddressList));
271
272
}

273
274
275
276
277
void MailWebEngineView::clearSelection()
{
    page()->runJavaScript(WebEngineViewer::WebEngineScript::clearSelection());
}

278
279
void MailWebEngineView::updateToggleFullAddressList(const QVariant &result)
{
Laurent Montel's avatar
Debug--    
Laurent Montel committed
280
    //qDebug() << " result" << result;
281
282
283
284
    if (result.isValid()) {
        const QList<QVariant> lst = result.toList();
        if (lst.count() == 1) {
            const QVariantMap map = lst.at(0).toMap();
Laurent Montel's avatar
Debug--    
Laurent Montel committed
285
            //qDebug() << "map !!!! " << map;
286
287
            const bool show = map.value(QStringLiteral("show")).toBool();
            const QString field = map.value(QStringLiteral("field")).toString();
Laurent Montel's avatar
Laurent Montel committed
288
            page()->runJavaScript(MessageViewer::MailWebEngineScript::updateToggleFullAddressList(field, show));
289
290
        }
    }
Laurent Montel's avatar
Laurent Montel committed
291
}
Laurent Montel's avatar
Laurent Montel committed
292
293
294

bool MailWebEngineView::hasVerticalScrollBar() const
{
295
    qDebug() << "bool MailWebEngineView::hasVerticalScrollBar() const not implemented";
Laurent Montel's avatar
Laurent Montel committed
296
297
298
299
300
301
    //TODO
    return false;
}

bool MailWebEngineView::isAttachmentInjectionPoint(const QPoint &globalPos) const
{
302
    qDebug() << "bool MailWebEngineView::isAttachmentInjectionPoint(const QPoint &globalPos) const not implemented";
Laurent Montel's avatar
Laurent Montel committed
303
304
305
306
    //TODO
    return false;
}

307
void MailWebEngineView::scrollToRelativePosition(qreal pos)
Laurent Montel's avatar
Laurent Montel committed
308
{
Laurent Montel's avatar
Laurent Montel committed
309
    page()->runJavaScript(WebEngineViewer::WebEngineScript::scrollToRelativePosition(pos));
Laurent Montel's avatar
Laurent Montel committed
310
311
}

312
qreal MailWebEngineView::relativePosition() const
Laurent Montel's avatar
Laurent Montel committed
313
{
314
315
316
#if QT_VERSION >= 0x050700
    return page()->scrollPosition().toPoint().y();
#endif
Laurent Montel's avatar
Laurent Montel committed
317
    qDebug() << "double MailWebEngineView::relativePosition() const not implemented";
Laurent Montel's avatar
Laurent Montel committed
318
319
320
321
322
323
324
325
326
327
    //TODO
    return {};
}

QUrl MailWebEngineView::linkOrImageUrlAt(const QPoint &global) const
{
    //TODO
    return {};
}

328
329
void MailWebEngineView::setAllowExternalContent(bool b)
{
Laurent Montel's avatar
Laurent Montel committed
330
331
332
333
    if (d->mExternalReference->allowExternalContent() != b) {
        d->mExternalReference->setAllowExternalContent(b);
        reload();
    }
334
}
Laurent Montel's avatar
Laurent Montel committed
335

Laurent Montel's avatar
Laurent Montel committed
336
QList<QAction *> MailWebEngineView::interceptorUrlActions(const WebEngineViewer::WebHitTestResult &result) const
Laurent Montel's avatar
Laurent Montel committed
337
{
Laurent Montel's avatar
Laurent Montel committed
338
    return d->mNetworkAccessManager->interceptorUrlActions(result);
Laurent Montel's avatar
Laurent Montel committed
339
340
341
342
343
344
}

void MailWebEngineView::slotLoadFinished()
{
    scamCheck();
}