Messagelib

webengineview.cpp
1/*
2 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "webengineview.h"
8#include "checkphishingurl/localdatabasemanager.h"
9#include "webenginemanagescript.h"
10#include "webenginenavigationrequestinterceptor.h"
11#include "webengineviewer_debug.h"
12#include <QEvent>
13#include <QKeyEvent>
14#include <QMouseEvent>
15#include <QTimer>
16#include <QWheelEvent>
17
18using namespace WebEngineViewer;
19
20class WebEngineViewer::WebEngineViewPrivate
21{
22public:
23 explicit WebEngineViewPrivate(WebEngineView *q)
24 : q(q)
25 {
26 }
27
28 ~WebEngineViewPrivate()
29 {
30 delete mWebEngineNavigatorInterceptor;
31 mWebEngineNavigatorInterceptor = nullptr;
32 delete mWebEngineNavigatorInterceptorView;
33 mWebEngineNavigatorInterceptorView = nullptr;
34 }
35
36 void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus status)
37 {
38 switch (status) {
39 case QWebEnginePage::NormalTerminationStatus:
40 return;
41
42 case QWebEnginePage::AbnormalTerminationStatus:
43 qCInfo(WEBENGINEVIEWER_LOG) << "WebEngine render process terminated abnormally";
44 break;
45 case QWebEnginePage::CrashedTerminationStatus:
46 qCInfo(WEBENGINEVIEWER_LOG) << "WebEngine render process crashed";
47 break;
48 case QWebEnginePage::KilledTerminationStatus:
49 qCInfo(WEBENGINEVIEWER_LOG) << "WebEngine render process killed";
50 break;
51 }
52
53 // don't get stuck in a loop if the renderer keeps crashing. Five restarts
54 // is an arbitrary constant.
55 if (++mCrashCount < 6) {
56 QTimer::singleShot(0, q, &QWebEngineView::reload);
57 } else {
58 // TODO: try to show a sadface page
59 }
60 }
61
62 qreal mSavedRelativePosition = -1;
63 QWidget *mCurrentWidget = nullptr;
64 WebEngineNavigationRequestInterceptor *mWebEngineNavigatorInterceptor = nullptr;
65 WebEngineView *mWebEngineNavigatorInterceptorView = nullptr;
66 LocalDataBaseManager *mPhishingDatabase = nullptr;
67 int mCrashCount = 0;
68
69private:
70 WebEngineView *const q;
71};
72
73WebEngineView::WebEngineView(QWidget *parent)
74 : QWebEngineView(parent)
75 , d(new WebEngineViewer::WebEngineViewPrivate(this))
76{
77 installEventFilter(this);
78
79 connect(this, &QWebEngineView::renderProcessTerminated, this, [this](QWebEnginePage::RenderProcessTerminationStatus status) {
80 d->renderProcessTerminated(status);
81 });
82 connect(this, &QWebEngineView::loadFinished, this, [this]() {
83 // Reset the crash counter if we manage to actually load a page.
84 // This does not perfectly correspond to "we managed to render
85 // a page", but it's the best we have
86 d->mCrashCount = 0;
87 });
88}
89
90WebEngineView::~WebEngineView() = default;
91
92void WebEngineView::forwardWheelEvent(QWheelEvent *event)
93{
94 Q_UNUSED(event)
95}
96
97void WebEngineView::forwardKeyPressEvent(QKeyEvent *event)
98{
99 Q_UNUSED(event)
100}
101
102void WebEngineView::forwardKeyReleaseEvent(QKeyEvent *event)
103{
104 Q_UNUSED(event)
105}
106
107void WebEngineView::forwardMousePressEvent(QMouseEvent *event)
108{
109 Q_UNUSED(event)
110}
111
112void WebEngineView::forwardMouseMoveEvent(QMouseEvent *event)
113{
114 Q_UNUSED(event)
115}
116
117void WebEngineView::forwardMouseReleaseEvent(QMouseEvent *event)
118{
119 Q_UNUSED(event)
120}
121
122bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
123{
124 // Keyboard events are sent to parent widget
125 if (obj == this && event->type() == QEvent::ParentChange && parentWidget()) {
126 parentWidget()->installEventFilter(this);
127 }
128
129 // Hack to find widget that receives input events
130 if (obj == this && event->type() == QEvent::ChildAdded) {
131 QTimer::singleShot(0, this, [this]() {
132 if (focusProxy() && d->mCurrentWidget != focusProxy()) {
133 d->mCurrentWidget = focusProxy();
134 d->mCurrentWidget->installEventFilter(this);
135 }
136 });
137 }
138
139 // Forward events to WebEngineView
140 if (obj == d->mCurrentWidget) {
141#define HANDLE_EVENT(f, t) \
142 { \
143 bool wasAccepted = event->isAccepted(); \
144 event->setAccepted(false); \
145 f(static_cast<t *>(event)); \
146 bool ret = event->isAccepted(); \
147 event->setAccepted(wasAccepted); \
148 return ret; \
149 }
150
151 switch (event->type()) {
152 case QEvent::KeyPress:
153 HANDLE_EVENT(forwardKeyPressEvent, QKeyEvent)
155 HANDLE_EVENT(forwardKeyReleaseEvent, QKeyEvent)
157 HANDLE_EVENT(forwardMousePressEvent, QMouseEvent)
159 HANDLE_EVENT(forwardMouseReleaseEvent, QMouseEvent)
161 HANDLE_EVENT(forwardMouseMoveEvent, QMouseEvent)
162 case QEvent::Wheel:
163 HANDLE_EVENT(forwardWheelEvent, QWheelEvent)
164 default:
165 break;
166 }
167
168#undef HANDLE_EVENT
169 }
170 // Block already handled events
171 if (obj == this) {
172 switch (event->type()) {
173 case QEvent::KeyPress:
178 case QEvent::Wheel:
179 return true;
180
181 default:
182 break;
183 }
184 }
185 return QWebEngineView::eventFilter(obj, event);
186}
187
188QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type)
189{
190 Q_UNUSED(type)
191 delete d->mWebEngineNavigatorInterceptor;
192 delete d->mWebEngineNavigatorInterceptorView;
193 d->mWebEngineNavigatorInterceptorView = new WebEngineView();
194
195 d->mWebEngineNavigatorInterceptor = new WebEngineNavigationRequestInterceptor(this->page());
196 d->mWebEngineNavigatorInterceptorView->setPage(d->mWebEngineNavigatorInterceptor);
197 return d->mWebEngineNavigatorInterceptorView;
198}
199
200void WebEngineView::clearRelativePosition()
201{
202 d->mSavedRelativePosition = -1;
203}
204
205void WebEngineView::saveRelativePosition()
206{
207 if (d->mSavedRelativePosition != -1) {
208 d->mSavedRelativePosition = page()->scrollPosition().toPoint().y();
209 }
210}
211
212qreal WebEngineView::relativePosition() const
213{
214 qCDebug(WEBENGINEVIEWER_LOG) << "Relative Position" << d->mSavedRelativePosition;
215 return d->mSavedRelativePosition;
216}
217
218LocalDataBaseManager *WebEngineView::phishingDatabase() const
219{
220 if (!d->mPhishingDatabase) {
221 d->mPhishingDatabase = new LocalDataBaseManager(const_cast<WebEngineView *>(this));
222 d->mPhishingDatabase->initialize();
223 }
224 return d->mPhishingDatabase;
225}
226
227#include "moc_webengineview.cpp"
The LocalDataBaseManager class.
The WebEngineView class.
Q_SCRIPTABLE CaptureState status()
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:12:44 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.