mailwebengineview.cpp 10.6 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
#include "webengine/webengineaccesskey/webengineaccesskey.h"
Laurent Montel's avatar
Laurent Montel committed
21
#include "webengine/webenginescript.h"
22
#include "messageviewer/messageviewersettings.h"
23
24
#include "loadexternalreferencesurlinterceptor/loadexternalreferencesurlinterceptor.h"
#include "cidreferencesurlinterceptor/cidreferencesurlinterceptor.h"
Laurent Montel's avatar
Laurent Montel committed
25
26
#include <MessageViewer/NetworkAccessManagerWebEngine>

Laurent Montel's avatar
Laurent Montel committed
27
#include "scamdetection/scamdetectionwebengine.h"
Laurent Montel's avatar
Laurent Montel committed
28
#include "scamdetection/scamcheckshorturl.h"
Laurent Montel's avatar
Laurent Montel committed
29
30
31
#include <QContextMenuEvent>
#include <MessageViewer/WebHitTest>
#include <MessageViewer/WebHitTestResult>
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

36
using namespace MessageViewer;
Laurent Montel's avatar
Laurent Montel committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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;
}
54

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

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

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

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

87
    d->mNetworkAccessManager = new MessageViewer::NetworkAccessManagerWebEngine(this, ac, this);
88
    d->mExternalReference = new MessageViewer::LoadExternalReferencesUrlInterceptor(this);
89
    d->mNetworkAccessManager->addInterceptor(d->mExternalReference);
Laurent Montel's avatar
Laurent Montel committed
90
91
    MessageViewer::CidReferencesUrlInterceptor *cidReference = new MessageViewer::CidReferencesUrlInterceptor(this);
    d->mNetworkAccessManager->addInterceptor(cidReference);
Laurent Montel's avatar
Laurent Montel committed
92
93
    d->mPageEngine = new MailWebEnginePage(this);
    setPage(d->mPageEngine);
94
    QWebEngineProfile::defaultProfile()->setHttpCacheType(QWebEngineProfile::MemoryHttpCache);
Laurent Montel's avatar
Laurent Montel committed
95
    setFocusPolicy(Qt::WheelFocus);
Laurent Montel's avatar
Laurent Montel committed
96
    connect(d->mPageEngine, &MailWebEnginePage::urlClicked, this, &MailWebEngineView::openUrl);
Laurent Montel's avatar
Laurent Montel committed
97
    //TODO need info about scrolling
98
99
}

Laurent Montel's avatar
Laurent Montel committed
100
MailWebEngineView::~MailWebEngineView()
101
{
Laurent Montel's avatar
Laurent Montel committed
102
    delete d;
103
}
Laurent Montel's avatar
Laurent Montel committed
104

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

void MailWebEngineView::slotWebHitFinished(const MessageViewer::WebHitTestResult &result)
{
Laurent Montel's avatar
Laurent Montel committed
113
    Q_EMIT popupMenu(result);
Laurent Montel's avatar
Laurent Montel committed
114
115
}

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

void MailWebEngineView::scrollDown(int pixels)
{
    page()->runJavaScript(MessageViewer::WebEngineScript::scrollDown(pixels));
}

Laurent Montel's avatar
Laurent Montel committed
126
127
128
129
void MailWebEngineView::selectAll()
{
    page()->triggerAction(QWebEnginePage::SelectAll);
}
Laurent Montel's avatar
Laurent Montel committed
130
131
132

void MailWebEngineView::slotZoomChanged(qreal zoom)
{
Laurent Montel's avatar
Laurent Montel committed
133
    qDebug() << " void MailWebEngineView::slotZoomChanged(qreal zoom)*******" << zoom;
Laurent Montel's avatar
Laurent Montel committed
134
135
136
    setZoomFactor(zoom);
}

Laurent Montel's avatar
Laurent Montel committed
137
138
139
140
141
void MailWebEngineView::scamCheck()
{
    d->mScamDetection->scanPage(page());
}

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

Laurent Montel's avatar
Laurent Montel committed
147
void MailWebEngineView::forwardKeyReleaseEvent(QKeyEvent *e)
148
149
{
    if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
150
        d->mWebViewAccessKey->keyReleaseEvent(e);
151
152
153
    }
}

Laurent Montel's avatar
Laurent Montel committed
154
void MailWebEngineView::forwardKeyPressEvent(QKeyEvent *e)
155
156
157
{
    if (e && hasFocus()) {
        if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
158
            d->mWebViewAccessKey->keyPressEvent(e);
159
160
161
162
        }
    }
}

Laurent Montel's avatar
Laurent Montel committed
163
void MailWebEngineView::forwardWheelEvent(QWheelEvent *e)
164
165
{
    if (MessageViewer::MessageViewerSettings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
166
        d->mWebViewAccessKey->wheelEvent(e);
167
168
169
170
171
172
    }
}

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

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
192
193
194
195
196

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

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

Laurent Montel's avatar
Laurent Montel committed
206
207
208
209
210
void MailWebEngineView::setElementByIdVisible(const QString &id, bool visible)
{
    page()->runJavaScript(MessageViewer::WebEngineScript::setElementByIdVisible(id, visible));
}

Laurent Montel's avatar
Laurent Montel committed
211
void MailWebEngineView::removeAttachmentMarking(const QString &id)
Laurent Montel's avatar
Laurent Montel committed
212
{
213
    page()->runJavaScript(MessageViewer::WebEngineScript::removeStyleToElement(QLatin1String("*#") + id));
Laurent Montel's avatar
Laurent Montel committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
}

void MailWebEngineView::markAttachment(const QString &id, const QString &style)
{
    //TODO verify "*#" + id
    page()->runJavaScript(MessageViewer::WebEngineScript::setStyleToElement(QLatin1String("*#") + id, style));
}

void MailWebEngineView::scrollToAnchor(const QString &anchor)
{
    page()->runJavaScript(MessageViewer::WebEngineScript::searchElementPosition(anchor), invoke(this, &MailWebEngineView::handleScrollToAnchor));
}

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());
            page()->runJavaScript(MessageViewer::WebEngineScript::scrollToPosition(pos));
        }
    }
}
237
238
239

void MailWebEngineView::scrollPageDown(int percent)
{
240
241
    page()->runJavaScript(MessageViewer::WebEngineScript::scrollPercentage(percent));
    qDebug()<<" void MailWebEngineView::scrollPageDown(int percent) not implemented";
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#if 0
    const qint64 height =  page()->viewportSize().height();
    const qint64 current = page()->mainFrame()->scrollBarValue(Qt::Vertical);
    // do arithmetic in higher precision, and check for overflow:
    const qint64 newPosition = current + height * percent / 100;
    if (newPosition > std::numeric_limits<int>::max()) {
        qCWarning(MESSAGEVIEWER_LOG) << "new position" << newPosition << "exceeds range of 'int'!";
    }
    page()->mainFrame()->setScrollBarValue(Qt::Vertical, newPosition);
#endif
}

void MailWebEngineView::scrollPageUp(int percent)
{
    scrollPageDown(-percent);
}
Laurent Montel's avatar
Laurent Montel committed
258
259
260

void MailWebEngineView::injectAttachments(const boost::function<QString()> &delayedHtml)
{
Laurent Montel's avatar
Laurent Montel committed
261
262
263
264
    const QString html = delayedHtml();
    if (html.isEmpty()) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
265
    page()->runJavaScript(MessageViewer::WebEngineScript::injectAttachments(html, QStringLiteral("attachmentInjectionPoint")));
Laurent Montel's avatar
Laurent Montel committed
266
267
}

268
void MailWebEngineView::toggleFullAddressList(const QString &field, const boost::function<QString()> &delayedHtml, bool doShow)
Laurent Montel's avatar
Laurent Montel committed
269
{
270
271
272
273
274
275
    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
276
    page()->runJavaScript(MessageViewer::WebEngineScript::toggleFullAddressList(field, QStringLiteral("attachmentInjectionPoint"), doShow));
Laurent Montel's avatar
Laurent Montel committed
277
}
Laurent Montel's avatar
Laurent Montel committed
278
279
280

bool MailWebEngineView::hasVerticalScrollBar() const
{
281
    qDebug() << "bool MailWebEngineView::hasVerticalScrollBar() const not implemented";
Laurent Montel's avatar
Laurent Montel committed
282
283
284
285
286
287
    //TODO
    return false;
}

bool MailWebEngineView::isAttachmentInjectionPoint(const QPoint &globalPos) const
{
288
    qDebug() << "bool MailWebEngineView::isAttachmentInjectionPoint(const QPoint &globalPos) const not implemented";
Laurent Montel's avatar
Laurent Montel committed
289
290
291
292
293
294
    //TODO
    return false;
}

void MailWebEngineView::scrollToRelativePosition(double pos)
{
Laurent Montel's avatar
Laurent Montel committed
295
    page()->runJavaScript(MessageViewer::WebEngineScript::scrollToRelativePosition(pos));
Laurent Montel's avatar
Laurent Montel committed
296
297
298
299
}

double MailWebEngineView::relativePosition() const
{
Laurent Montel's avatar
Laurent Montel committed
300

301
    qDebug()<<"double MailWebEngineView::relativePosition() const not implemented";
Laurent Montel's avatar
Laurent Montel committed
302
303
304
305
306
307
308
309
310
311
    //TODO
    return {};
}

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

312
313
void MailWebEngineView::setAllowExternalContent(bool b)
{
Laurent Montel's avatar
Laurent Montel committed
314
315
316
317
    if (d->mExternalReference->allowExternalContent() != b) {
        d->mExternalReference->setAllowExternalContent(b);
        reload();
    }
318
}
Laurent Montel's avatar
Laurent Montel committed
319

320
QList<QAction *> MailWebEngineView::interceptorUrlActions(const MessageViewer::WebHitTestResult &result) const
Laurent Montel's avatar
Laurent Montel committed
321
{
Laurent Montel's avatar
Laurent Montel committed
322
    return d->mNetworkAccessManager->interceptorUrlActions(result);
Laurent Montel's avatar
Laurent Montel committed
323
324
325
326
327
328
}

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