articleviewerwebengine.cpp 18.7 KB
Newer Older
Laurent Montel's avatar
Laurent Montel committed
1
/*
Laurent Montel's avatar
Laurent Montel committed
2
   Copyright (C) 2015-2020 Laurent Montel <montel@kde.org>
Laurent Montel's avatar
Laurent Montel committed
3

Laurent Montel's avatar
Laurent Montel committed
4
5
6
7
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
Laurent Montel's avatar
Laurent Montel committed
8

Laurent Montel's avatar
Laurent Montel committed
9
10
11
12
   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.
Laurent Montel's avatar
Laurent Montel committed
13

Laurent Montel's avatar
Laurent Montel committed
14
15
16
17
   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  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
19
20
*/

#include "articleviewerwebengine.h"
Laurent Montel's avatar
Laurent Montel committed
21
22
#include "akregator_debug.h"
#include "articleviewerwebenginepage.h"
23
#include "webengine/urlhandlerwebenginemanager.h"
24
#include <WebEngineViewer/ZoomActionMenu>
Laurent Montel's avatar
Laurent Montel committed
25
26
27
#include "actionmanager.h"
#include "akregatorconfig.h"
#include "actions/actions.h"
Laurent Montel's avatar
Laurent Montel committed
28
#include "urlhandler/webengine/urlhandlerwebengine.h"
Laurent Montel's avatar
Laurent Montel committed
29
#include <WebEngineViewer/InterceptorManager>
30
#include <WebEngineViewer/WebEngineAccessKey>
31
#include <WebEngineViewer/WebEngineManageScript>
Laurent Montel's avatar
Laurent Montel committed
32
33
34
#include <KPIMTextEdit/TextToSpeech>

#include <KParts/BrowserRun>
35
#include <GrantleeTheme/GrantleeThemeManager>
Laurent Montel's avatar
Laurent Montel committed
36
37
38
#include <KActionCollection>
#include <KLocalizedString>
#include <KAboutData>
Laurent Montel's avatar
Laurent Montel committed
39
40
41
42
43
44
45
46
#include <KGuiItem>
#include <openurlrequest.h>
#include <KMessageBox>
#include <QPrinter>
#include <QMouseEvent>
#include <QApplication>
#include <QClipboard>
#include <QMenu>
47
#include <viewerplugintoolmanager.h>
Laurent Montel's avatar
Laurent Montel committed
48
#include <QWebEngineProfile>
Andras Mantia's avatar
Andras Mantia committed
49
#include <QWebEngineUrlRequestInterceptor>
Laurent Montel's avatar
Laurent Montel committed
50
#include <QtWebEngineWidgetsVersion>
51

52
53
#include <WebEngineViewer/WebHitTestResult>
#include <WebEngineViewer/WebHitTest>
Laurent Montel's avatar
Laurent Montel committed
54
#include <WebEngineViewer/WebEngineScript>
Laurent Montel's avatar
Laurent Montel committed
55

56
57
#include <WebEngineViewer/LocalDataBaseManager>

Laurent Montel's avatar
Laurent Montel committed
58
#include <KIO/KUriFilterSearchProviderActions>
Laurent Montel's avatar
Laurent Montel committed
59
60
61

using namespace Akregator;

Andras Mantia's avatar
Andras Mantia committed
62
63
64
65
66
class AkregatorRequestInterceptor : public QWebEngineUrlRequestInterceptor
{
    Q_OBJECT

public:
Laurent Montel's avatar
Laurent Montel committed
67
68
    explicit AkregatorRequestInterceptor(QObject *parent = nullptr) : QWebEngineUrlRequestInterceptor(parent)
    {
Andras Mantia's avatar
Andras Mantia committed
69
70
    }

Laurent Montel's avatar
Laurent Montel committed
71
72
    void interceptRequest(QWebEngineUrlRequestInfo &info) override
    {
Andras Mantia's avatar
Andras Mantia committed
73
74
75
76
        Q_UNUSED(info);
    }
};

Laurent Montel's avatar
Laurent Montel committed
77
ArticleViewerWebEngine::ArticleViewerWebEngine(KActionCollection *ac, QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
78
79
80
81
    : WebEngineViewer::WebEngineView(parent)
    , mActionCollection(ac)
    , mLastButtonClicked(LeftButton)
    , mViewerPluginToolManager(nullptr)
Laurent Montel's avatar
Laurent Montel committed
82
{
Wolfgang Bauer's avatar
Wolfgang Bauer committed
83
    mNetworkAccessManager = new WebEngineViewer::InterceptorManager(this, ac, this);
Andras Mantia's avatar
Andras Mantia committed
84

85
86
    mPageEngine = new ArticleViewerWebEnginePage(this);
    QWebEngineProfile *profile = mPageEngine->profile();
Laurent Montel's avatar
Laurent Montel committed
87
    profile->setPersistentCookiesPolicy(QWebEngineProfile::ForcePersistentCookies);
Laurent Montel's avatar
Minor    
Laurent Montel committed
88

Andras Mantia's avatar
Andras Mantia committed
89
90
    // Needed to workaround crash in webengine, see https://bugreports.qt.io/browse/QTBUG-72260
    auto webEngineUrlInterceptor = new AkregatorRequestInterceptor();
91
    connect(profile, &QObject::destroyed, webEngineUrlInterceptor, &AkregatorRequestInterceptor::deleteLater);
92
    profile->setUrlRequestInterceptor(webEngineUrlInterceptor);
Andras Mantia's avatar
Andras Mantia committed
93

Laurent Montel's avatar
Laurent Montel committed
94
    setPage(mPageEngine);
Laurent Montel's avatar
Laurent Montel committed
95

Laurent Montel's avatar
Laurent Montel committed
96
97
    connect(this, &ArticleViewerWebEngine::showContextMenu, this, &ArticleViewerWebEngine::slotShowContextMenu);

Laurent Montel's avatar
Laurent Montel committed
98
    setFocusPolicy(Qt::WheelFocus);
Laurent Montel's avatar
Laurent Montel committed
99
    connect(mPageEngine, &ArticleViewerWebEnginePage::urlClicked, this, &ArticleViewerWebEngine::slotLinkClicked);
Laurent Montel's avatar
Laurent Montel committed
100

101
    mWebEngineViewAccessKey = new WebEngineViewer::WebEngineAccessKey(this, this);
Laurent Montel's avatar
Laurent Montel committed
102
    mWebEngineViewAccessKey->setActionCollection(mActionCollection);
103
    connect(mWebEngineViewAccessKey, &WebEngineViewer::WebEngineAccessKey::openUrl, this, &ArticleViewerWebEngine::slotLinkClicked);
Laurent Montel's avatar
Laurent Montel committed
104
105
106
107
108

    connect(this, &ArticleViewerWebEngine::loadStarted, this, &ArticleViewerWebEngine::slotLoadStarted);
    connect(this, &ArticleViewerWebEngine::loadFinished, this, &ArticleViewerWebEngine::slotLoadFinished);
    connect(page(), &QWebEnginePage::linkHovered, this, &ArticleViewerWebEngine::slotLinkHovered);

Laurent Montel's avatar
Laurent Montel committed
109
    setContextMenuPolicy(Qt::DefaultContextMenu);
Laurent Montel's avatar
Laurent Montel committed
110
111
112
    mWebShortcutMenuManager = new KIO::KUriFilterSearchProviderActions(this);
    mShareServiceManager = new PimCommon::ShareServiceUrlManager(this);
    connect(mShareServiceManager, &PimCommon::ShareServiceUrlManager::serviceUrlSelected, this, &ArticleViewerWebEngine::slotServiceUrlSelected);
113
114
115
116
    connect(page(), &QWebEnginePage::audioMutedChanged,
            this, &ArticleViewerWebEngine::slotWebPageMutedOrAudibleChanged);
    connect(page(), &QWebEnginePage::recentlyAudibleChanged,
            this, &ArticleViewerWebEngine::slotWebPageMutedOrAudibleChanged);
117

118
119
    connect(phishingDatabase(), &WebEngineViewer::LocalDataBaseManager::checkUrlFinished,
            this, &ArticleViewerWebEngine::slotCheckedUrlFinished);
Laurent Montel's avatar
Laurent Montel committed
120
121
122
123
124
}

ArticleViewerWebEngine::~ArticleViewerWebEngine()
{
}
Laurent Montel's avatar
Laurent Montel committed
125

Laurent Montel's avatar
Laurent Montel committed
126
127
void ArticleViewerWebEngine::execPrintPreviewPage(QPrinter *printer, int timeout)
{
Laurent Montel's avatar
Laurent Montel committed
128
129
130
    if (!mPageEngine->execPrintPreviewPage(printer, timeout)) {
        qCWarning(AKREGATOR_LOG) << "Impossible to print page";
    }
Laurent Montel's avatar
Laurent Montel committed
131
132
}

133
134
135
136
137
void ArticleViewerWebEngine::slotWebPageMutedOrAudibleChanged()
{
    Q_EMIT webPageMutedOrAudibleChanged(page()->isAudioMuted(), page()->recentlyAudible());
}

Laurent Montel's avatar
Laurent Montel committed
138
139
140
141
142
143
144
145
146
147
148
149
QVariantHash ArticleViewerWebEngine::introductionData() const
{
    QVariantHash data;
    data[QStringLiteral("icon")] = QStringLiteral("akregator");
    data[QStringLiteral("name")] = i18n("Akregator");
    data[QStringLiteral("subtitle")] = i18n("Akregator is a KDE news feed reader.");
    data[QStringLiteral("version")] = KAboutData::applicationData().version();
    return data;
}

void ArticleViewerWebEngine::showAboutPage()
{
Laurent Montel's avatar
Laurent Montel committed
150
    paintAboutScreen(QStringLiteral(":/about/introduction_akregator.html"), introductionData());
Laurent Montel's avatar
Laurent Montel committed
151
152
153
154
155
156
}

void ArticleViewerWebEngine::paintAboutScreen(const QString &templateName, const QVariantHash &data)
{
    GrantleeTheme::ThemeManager manager(QStringLiteral("splashPage"),
                                        QStringLiteral("splash.theme"),
Laurent Montel's avatar
Laurent Montel committed
157
                                        nullptr,
Laurent Montel's avatar
Laurent Montel committed
158
159
                                        QStringLiteral("messageviewer/about/"));
    GrantleeTheme::Theme theme = manager.theme(QStringLiteral("default"));
Laurent Montel's avatar
Laurent Montel committed
160
    if (theme.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
161
        setHtml(theme.render(templateName, data, QByteArrayLiteral("akregator")),
Laurent Montel's avatar
Laurent Montel committed
162
                QUrl::fromLocalFile(theme.absolutePath() + QLatin1Char('/')));
Laurent Montel's avatar
Laurent Montel committed
163
164
    } else {
        qCDebug(AKREGATOR_LOG) << "Theme error: failed to find splash theme";
Laurent Montel's avatar
Laurent Montel committed
165
166
167
    }
}

Laurent Montel's avatar
Laurent Montel committed
168
void ArticleViewerWebEngine::slotServiceUrlSelected(PimCommon::ShareServiceUrlManager::ServiceType type)
Laurent Montel's avatar
Laurent Montel committed
169
{
170
171
172
    if (mCurrentUrl.isEmpty()) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
173
174
    const QUrl url = mShareServiceManager->generateServiceUrl(mCurrentUrl.url(), QString(), type);
    mShareServiceManager->openUrl(url);
Laurent Montel's avatar
Laurent Montel committed
175
176
}

Laurent Montel's avatar
Laurent Montel committed
177
void ArticleViewerWebEngine::slotSaveLinkAs()
Laurent Montel's avatar
Laurent Montel committed
178
179
180
181
182
183
184
{
    QUrl tmp(mCurrentUrl);

    if (tmp.fileName().isEmpty()) {
        tmp = tmp.adjusted(QUrl::RemoveFilename);
        tmp.setPath(tmp.path() + QLatin1String("index.html"));
    }
Laurent Montel's avatar
Laurent Montel committed
185
    KParts::BrowserRun::saveUrl(tmp, tmp.fileName(), this, {});
Laurent Montel's avatar
Laurent Montel committed
186
187
}

Laurent Montel's avatar
Laurent Montel committed
188
void ArticleViewerWebEngine::slotSaveImageOnDiskInFrame()
Laurent Montel's avatar
Laurent Montel committed
189
190
191
192
{
    slotSaveLinkAs();
}

Laurent Montel's avatar
Laurent Montel committed
193
void ArticleViewerWebEngine::slotCopyImageLocationInFrame()
Laurent Montel's avatar
Laurent Montel committed
194
195
196
197
{
    slotCopyLinkAddress();
}

Laurent Montel's avatar
Laurent Montel committed
198
199
200
201
202
void ArticleViewerWebEngine::slotMute(bool mute)
{
    page()->setAudioMuted(mute);
}

Laurent Montel's avatar
Laurent Montel committed
203
void ArticleViewerWebEngine::slotCopyLinkAddress()
Laurent Montel's avatar
Laurent Montel committed
204
205
206
207
208
209
210
211
212
213
214
215
{
    if (mCurrentUrl.isEmpty()) {
        return;
    }
    QClipboard *cb = QApplication::clipboard();
    cb->setText(mCurrentUrl.toString(), QClipboard::Clipboard);
    // don't set url to selection as it's a no-no according to a fd.o spec
    // which spec? Nobody seems to care (tested Firefox (3.5.10) Konqueror,and KMail (4.2.3)), so I re-enable the following line unless someone gives
    // a good reason to remove it again (bug 183022) --Frank
    cb->setText(mCurrentUrl.toString(), QClipboard::Selection);
}

Laurent Montel's avatar
Laurent Montel committed
216
217
218
219
220
void ArticleViewerWebEngine::contextMenuEvent(QContextMenuEvent *e)
{
    displayContextMenu(e->pos());
}

Laurent Montel's avatar
Laurent Montel committed
221
void ArticleViewerWebEngine::slotShowContextMenu(const QPoint &pos)
Laurent Montel's avatar
Laurent Montel committed
222
223
224
225
{
    displayContextMenu(pos);
}

Laurent Montel's avatar
Laurent Montel committed
226
void ArticleViewerWebEngine::slotCopy()
Laurent Montel's avatar
Laurent Montel committed
227
{
Laurent Montel's avatar
Laurent Montel committed
228
    triggerPageAction(QWebEnginePage::Copy);
Laurent Montel's avatar
Laurent Montel committed
229
230
}

Laurent Montel's avatar
Laurent Montel committed
231
void ArticleViewerWebEngine::slotLoadFinished()
Laurent Montel's avatar
Laurent Montel committed
232
{
233
    restoreCurrentPosition();
Laurent Montel's avatar
Laurent Montel committed
234
235
236
    unsetCursor();
}

Laurent Montel's avatar
Laurent Montel committed
237
void ArticleViewerWebEngine::slotLoadStarted()
Laurent Montel's avatar
Laurent Montel committed
238
{
Laurent Montel's avatar
Laurent Montel committed
239
    mWebEngineViewAccessKey->hideAccessKeys();
Laurent Montel's avatar
Laurent Montel committed
240
241
242
    setCursor(Qt::WaitCursor);
}

243
void ArticleViewerWebEngine::slotWebHitFinished(const WebEngineViewer::WebHitTestResult &result)
Laurent Montel's avatar
Laurent Montel committed
244
{
245
246
    mCurrentUrl = result.linkUrl();
    if (URLHandlerWebEngineManager::instance()->handleContextMenuRequest(mCurrentUrl, mapToGlobal(result.pos()), this)) {
Laurent Montel's avatar
Laurent Montel committed
247
248
249
250
        return;
    }

    QMenu popup(this);
Laurent Montel's avatar
Laurent Montel committed
251
252
    const bool noContentSelected = selectedText().isEmpty();
    if (noContentSelected) {
Laurent Montel's avatar
Laurent Montel committed
253
        if (!mCurrentUrl.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
254
255
            {
                QAction *act = createOpenLinkInNewTabAction(mCurrentUrl, &popup);
256
                connect(act, &QAction::triggered, this, &ArticleViewerWebEngine::slotOpenLinkInBackgroundTab);
Laurent Montel's avatar
Laurent Montel committed
257
258
259
260
261
262
263
                popup.addAction(act);
            }
            {
                QAction *act = createOpenLinkInExternalBrowserAction(mCurrentUrl, &popup);
                connect(act, &QAction::triggered, this, &ArticleViewerWebEngine::slotOpenLinkInBrowser);
                popup.addAction(act);
            }
Laurent Montel's avatar
Laurent Montel committed
264
265
266
267
            popup.addSeparator();
            popup.addAction(mActionCollection->action(QStringLiteral("savelinkas")));
            popup.addAction(mActionCollection->action(QStringLiteral("copylinkaddress")));
        }
268
        if (!result.imageUrl().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
269
270
271
272
            popup.addSeparator();
            popup.addAction(mActionCollection->action(QStringLiteral("copy_image_location")));
            popup.addAction(mActionCollection->action(QStringLiteral("saveas_imageurl")));
        }
Laurent Montel's avatar
Laurent Montel committed
273
274
        popup.addSeparator();
        popup.addActions(viewerPluginActionList(MessageViewer::ViewerPluginInterface::NeedUrl));
Laurent Montel's avatar
Laurent Montel committed
275
276
277
        popup.addSeparator();
        popup.addAction(mShareServiceManager->menu());
    } else {
Laurent Montel's avatar
Laurent Montel committed
278
279
280
281
        popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_copy")));
        popup.addSeparator();
        mWebShortcutMenuManager->setSelectedText(page()->selectedText());
        mWebShortcutMenuManager->addWebShortcutsToMenu(&popup);
282
283
        popup.addSeparator();
        popup.addActions(viewerPluginActionList(MessageViewer::ViewerPluginInterface::NeedSelection));
Laurent Montel's avatar
Laurent Montel committed
284
285
286
287
    }
    popup.addSeparator();
    popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_print")));
    popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_printpreview")));
Laurent Montel's avatar
Laurent Montel committed
288
    popup.addSeparator();
Laurent Montel's avatar
Laurent Montel committed
289
290
    popup.addAction(ActionManager::getInstance()->action(QStringLiteral("tab_mute")));
    popup.addAction(ActionManager::getInstance()->action(QStringLiteral("tab_unmute")));
Laurent Montel's avatar
Laurent Montel committed
291
292
293
294
295
296
    popup.addSeparator();
    popup.addAction(ActionManager::getInstance()->action(QStringLiteral("find_in_messages")));
    if (KPIMTextEdit::TextToSpeech::self()->isReady()) {
        popup.addSeparator();
        popup.addAction(ActionManager::getInstance()->action(QStringLiteral("speak_text")));
    }
297
298
299
300
301
    popup.exec(mapToGlobal(result.pos()));
}

void ArticleViewerWebEngine::displayContextMenu(const QPoint &pos)
{
302
303
    WebEngineViewer::WebHitTest *webHit = mPageEngine->hitTestContent(pos);
    connect(webHit, &WebEngineViewer::WebHitTest::finished, this, &ArticleViewerWebEngine::slotWebHitFinished);
Laurent Montel's avatar
Laurent Montel committed
304
305
}

Laurent Montel's avatar
Laurent Montel committed
306
void ArticleViewerWebEngine::slotLinkHovered(const QString &link)
Laurent Montel's avatar
Laurent Montel committed
307
{
Laurent Montel's avatar
Laurent Montel committed
308
    QString msg = URLHandlerWebEngineManager::instance()->statusBarMessage(QUrl(link), this);
Laurent Montel's avatar
Laurent Montel committed
309
310
311
312
313
314
315
    if (msg.isEmpty()) {
        msg = link;
    }

    Q_EMIT showStatusBarMessage(msg);
}

Laurent Montel's avatar
Laurent Montel committed
316
void ArticleViewerWebEngine::forwardKeyReleaseEvent(QKeyEvent *e)
Laurent Montel's avatar
Laurent Montel committed
317
318
{
    if (Settings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
319
        mWebEngineViewAccessKey->keyReleaseEvent(e);
Laurent Montel's avatar
Laurent Montel committed
320
321
322
    }
}

Laurent Montel's avatar
Laurent Montel committed
323
void ArticleViewerWebEngine::forwardKeyPressEvent(QKeyEvent *e)
Laurent Montel's avatar
Laurent Montel committed
324
325
326
{
    if (e && hasFocus()) {
        if (Settings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
327
            mWebEngineViewAccessKey->keyPressEvent(e);
Laurent Montel's avatar
Laurent Montel committed
328
329
330
331
        }
    }
}

Laurent Montel's avatar
Laurent Montel committed
332
void ArticleViewerWebEngine::forwardWheelEvent(QWheelEvent *e)
Laurent Montel's avatar
Laurent Montel committed
333
334
{
    if (Settings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
335
        mWebEngineViewAccessKey->wheelEvent(e);
Laurent Montel's avatar
Laurent Montel committed
336
    }
337
    if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
338
        const int numDegrees = e->angleDelta().y() / 8;
339
340
341
342
343
344
        const int numSteps = numDegrees / 15;
        const qreal factor = ActionManager::getInstance()->zoomActionMenu()->zoomFactor() + numSteps * 10;
        if (factor >= 10 && factor <= 300) {
            ActionManager::getInstance()->zoomActionMenu()->setZoomFactor(factor);
            ActionManager::getInstance()->zoomActionMenu()->setWebViewerZoomFactor(factor / 100.0);
        }
Laurent Montel's avatar
Laurent Montel committed
345
        e->accept();
346
    }
Laurent Montel's avatar
Laurent Montel committed
347
348
}

Laurent Montel's avatar
Laurent Montel committed
349
void ArticleViewerWebEngine::resizeEvent(QResizeEvent *e)
Laurent Montel's avatar
Laurent Montel committed
350
351
{
    if (Settings::self()->accessKeyEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
352
        mWebEngineViewAccessKey->resizeEvent(e);
Laurent Montel's avatar
Laurent Montel committed
353
    }
Laurent Montel's avatar
Laurent Montel committed
354
    QWebEngineView::resizeEvent(e);
Laurent Montel's avatar
Laurent Montel committed
355
356
}

Laurent Montel's avatar
Laurent Montel committed
357
void ArticleViewerWebEngine::disableIntroduction()
Laurent Montel's avatar
Laurent Montel committed
358
359
360
361
362
363
364
365
366
367
368
369
{
    KGuiItem yesButton(KStandardGuiItem::yes());
    yesButton.setText(i18n("Disable"));
    KGuiItem noButton(KStandardGuiItem::no());
    noButton.setText(i18n("Keep Enabled"));
    if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to disable this introduction page?"),
                                   i18n("Disable Introduction Page"), yesButton, noButton) == KMessageBox::Yes) {
        Settings::self()->setDisableIntroduction(true);
        Settings::self()->save();
    }
}

Laurent Montel's avatar
Laurent Montel committed
370
void ArticleViewerWebEngine::setArticleAction(ArticleViewerWebEngine::ArticleAction type, const QString &articleId, const QString &feed)
Laurent Montel's avatar
Laurent Montel committed
371
372
373
374
{
    Q_EMIT articleAction(type, articleId, feed);
}

375
376
void ArticleViewerWebEngine::restoreCurrentPosition()
{
377
    mPageEngine->runJavaScript(WebEngineViewer::WebEngineScript::scrollToRelativePosition(0), WebEngineViewer::WebEngineManageScript::scriptWordId());
378
379
}

Laurent Montel's avatar
Laurent Montel committed
380
void ArticleViewerWebEngine::forwardMouseReleaseEvent(QMouseEvent *event)
Laurent Montel's avatar
Laurent Montel committed
381
382
383
384
385
386
387
388
389
390
391
{
    if (event->button() & Qt::RightButton) {
        Q_EMIT showContextMenu(event->pos());
        mLastButtonClicked = RightButton;
    } else if (event->button() & Qt::MiddleButton) {
        mLastButtonClicked = MiddleButton;
    } else if (event->button() & Qt::LeftButton) {
        mLastButtonClicked = LeftButton;
    }
}

Laurent Montel's avatar
Laurent Montel committed
392
393
394
395
396
397
398
399
bool ArticleViewerWebEngine::urlIsAMalwareButContinue()
{
    if (KMessageBox::No == KMessageBox::warningYesNo(this, i18n("This web site is a malware, do you want to continue to show it?"), i18n("Malware"))) {
        return false;
    }
    return true;
}

400
void ArticleViewerWebEngine::slotCheckedUrlFinished(const QUrl &url, WebEngineViewer::CheckPhishingUrlUtil::UrlStatus status)
Laurent Montel's avatar
Laurent Montel committed
401
402
{
    switch (status) {
Laurent Montel's avatar
Laurent Montel committed
403
    case WebEngineViewer::CheckPhishingUrlUtil::BrokenNetwork:
Laurent Montel's avatar
Laurent Montel committed
404
405
        KMessageBox::error(this, i18n("The network is broken."), i18n("Check Phishing Url"));
        break;
Laurent Montel's avatar
Laurent Montel committed
406
    case WebEngineViewer::CheckPhishingUrlUtil::InvalidUrl:
Laurent Montel's avatar
Laurent Montel committed
407
408
        KMessageBox::error(this, i18n("The url %1 is not valid.", url.toString()), i18n("Check Phishing Url"));
        break;
Laurent Montel's avatar
Laurent Montel committed
409
    case WebEngineViewer::CheckPhishingUrlUtil::Ok:
Laurent Montel's avatar
Laurent Montel committed
410
        break;
Laurent Montel's avatar
Laurent Montel committed
411
    case WebEngineViewer::CheckPhishingUrlUtil::MalWare:
Laurent Montel's avatar
Laurent Montel committed
412
        if (!urlIsAMalwareButContinue()) {
Laurent Montel's avatar
Laurent Montel committed
413
414
415
            return;
        }
        break;
Laurent Montel's avatar
Laurent Montel committed
416
    case WebEngineViewer::CheckPhishingUrlUtil::Unknown:
417
        qCWarning(AKREGATOR_LOG) << "ArticleViewerWebEngine::slotCheckedUrlFinished unknown error ";
Laurent Montel's avatar
Laurent Montel committed
418
419
        break;
    }
Laurent Montel's avatar
Laurent Montel committed
420
    openSafeUrl(url);
Laurent Montel's avatar
Laurent Montel committed
421
422
}

Laurent Montel's avatar
Laurent Montel committed
423
void ArticleViewerWebEngine::slotLinkClicked(const QUrl &url)
Laurent Montel's avatar
Laurent Montel committed
424
{
Laurent Montel's avatar
Laurent Montel committed
425
    if (URLHandlerWebEngineManager::instance()->handleClick(url, this)) {
Laurent Montel's avatar
Laurent Montel committed
426
427
        return;
    }
428
    if (Settings::checkPhishingUrl()) {
429
        phishingDatabase()->checkUrl(url);
430
431
432
    } else {
        openSafeUrl(url);
    }
Laurent Montel's avatar
Laurent Montel committed
433
434
435
436
}

void ArticleViewerWebEngine::openSafeUrl(const QUrl &url)
{
Laurent Montel's avatar
Laurent Montel committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
    mCurrentUrl = url;
    OpenUrlRequest req(mCurrentUrl);
    if (mLastButtonClicked == LeftButton) {
        switch (Settings::lMBBehaviour()) {
        case Settings::EnumLMBBehaviour::OpenInExternalBrowser:
            req.setOptions(OpenUrlRequest::ExternalBrowser);
            break;
        case Settings::EnumLMBBehaviour::OpenInBackground:
            req.setOpenInBackground(true);
            req.setOptions(OpenUrlRequest::NewTab);
            break;
        default:
            break;
        }
    } else if (mLastButtonClicked == MiddleButton) {
        switch (Settings::mMBBehaviour()) {
        case Settings::EnumMMBBehaviour::OpenInExternalBrowser:
            req.setOptions(OpenUrlRequest::ExternalBrowser);
            break;
        case Settings::EnumMMBBehaviour::OpenInBackground:
            req.setOpenInBackground(true);
            req.setOptions(OpenUrlRequest::NewTab);
            break;
        default:
            break;
        }
    }
    Q_EMIT signalOpenUrlRequest(req);
}

Laurent Montel's avatar
Laurent Montel committed
467
void ArticleViewerWebEngine::slotOpenLinkInForegroundTab()
Laurent Montel's avatar
Laurent Montel committed
468
469
470
471
472
473
{
    OpenUrlRequest req(mCurrentUrl);
    req.setOptions(OpenUrlRequest::NewTab);
    Q_EMIT signalOpenUrlRequest(req);
}

Laurent Montel's avatar
Laurent Montel committed
474
void ArticleViewerWebEngine::slotOpenLinkInBackgroundTab()
Laurent Montel's avatar
Laurent Montel committed
475
476
477
478
479
480
481
{
    OpenUrlRequest req(mCurrentUrl);
    req.setOptions(OpenUrlRequest::NewTab);
    req.setOpenInBackground(true);
    Q_EMIT signalOpenUrlRequest(req);
}

Laurent Montel's avatar
Laurent Montel committed
482
void ArticleViewerWebEngine::slotOpenLinkInBrowser()
Laurent Montel's avatar
Laurent Montel committed
483
484
485
486
487
488
{
    OpenUrlRequest req(mCurrentUrl);
    req.setOptions(OpenUrlRequest::ExternalBrowser);
    Q_EMIT signalOpenUrlRequest(req);
}

489
490
491
492
493
void ArticleViewerWebEngine::createViewerPluginToolManager(KActionCollection *ac, QWidget *parent)
{
    mViewerPluginToolManager = new MessageViewer::ViewerPluginToolManager(parent, this);
    mViewerPluginToolManager->setActionCollection(ac);
    mViewerPluginToolManager->setPluginName(QStringLiteral("akregator"));
494
    mViewerPluginToolManager->setPluginDirectory(QStringLiteral("akregator/viewerplugin"));
495
    if (!mViewerPluginToolManager->initializePluginList()) {
Laurent Montel's avatar
Laurent Montel committed
496
        qCWarning(AKREGATOR_LOG) << " Impossible to initialize plugins";
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
    }
    mViewerPluginToolManager->createView();
    connect(mViewerPluginToolManager, &MessageViewer::ViewerPluginToolManager::activatePlugin, this, &ArticleViewerWebEngine::slotActivatePlugin);
}

QList<QAction *> ArticleViewerWebEngine::viewerPluginActionList(MessageViewer::ViewerPluginInterface::SpecificFeatureTypes features)
{
    if (mViewerPluginToolManager) {
        return mViewerPluginToolManager->viewerPluginActionList(features);
    }
    return QList<QAction *>();
}

void ArticleViewerWebEngine::slotActivatePlugin(MessageViewer::ViewerPluginInterface *interface)
{
    const QString text = selectedText();
    if (!text.isEmpty()) {
        interface->setText(text);
    }
Laurent Montel's avatar
Laurent Montel committed
516
    interface->setUrl(mCurrentUrl);
Laurent Montel's avatar
Laurent Montel committed
517
    interface->execute();
518
}
Andras Mantia's avatar
Andras Mantia committed
519
520

#include "articleviewerwebengine.moc"