Messagelib

webengineview.cpp
1 /*
2  SPDX-FileCopyrightText: 2016-2023 Laurent Montel <[email protected]>
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 
18 using namespace WebEngineViewer;
19 
20 class WebEngineViewer::WebEngineViewPrivate
21 {
22 public:
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  WebEngineManageScript *mManagerScript = nullptr;
65  WebEngineNavigationRequestInterceptor *mWebEngineNavigatorInterceptor = nullptr;
66  WebEngineView *mWebEngineNavigatorInterceptorView = nullptr;
67  LocalDataBaseManager *mPhishingDatabase = nullptr;
68  int mCrashCount = 0;
69 
70 private:
71  WebEngineView *const q;
72 };
73 
74 WebEngineView::WebEngineView(QWidget *parent)
75  : QWebEngineView(parent)
76  , d(new WebEngineViewer::WebEngineViewPrivate(this))
77 {
78  installEventFilter(this);
79  d->mManagerScript = new WebEngineManageScript(this);
80 
81  connect(this, &QWebEngineView::renderProcessTerminated, this, [this](QWebEnginePage::RenderProcessTerminationStatus status) {
82  d->renderProcessTerminated(status);
83  });
84  connect(this, &QWebEngineView::loadFinished, this, [this]() {
85  // Reset the crash counter if we manage to actually load a page.
86  // This does not perfectly correspond to "we managed to render
87  // a page", but it's the best we have
88  d->mCrashCount = 0;
89  });
90 }
91 
92 WebEngineView::~WebEngineView() = default;
93 
94 WebEngineManageScript *WebEngineView::webEngineManagerScript() const
95 {
96  return d->mManagerScript;
97 }
98 
99 void WebEngineView::forwardWheelEvent(QWheelEvent *event)
100 {
101  Q_UNUSED(event)
102 }
103 
104 void WebEngineView::forwardKeyPressEvent(QKeyEvent *event)
105 {
106  Q_UNUSED(event)
107 }
108 
109 void WebEngineView::forwardKeyReleaseEvent(QKeyEvent *event)
110 {
111  Q_UNUSED(event)
112 }
113 
114 void WebEngineView::forwardMousePressEvent(QMouseEvent *event)
115 {
116  Q_UNUSED(event)
117 }
118 
119 void WebEngineView::forwardMouseMoveEvent(QMouseEvent *event)
120 {
121  Q_UNUSED(event)
122 }
123 
124 void WebEngineView::forwardMouseReleaseEvent(QMouseEvent *event)
125 {
126  Q_UNUSED(event)
127 }
128 
129 bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
130 {
131  // Keyboard events are sent to parent widget
132  if (obj == this && event->type() == QEvent::ParentChange && parentWidget()) {
133  parentWidget()->installEventFilter(this);
134  }
135 
136  // Hack to find widget that receives input events
137  if (obj == this && event->type() == QEvent::ChildAdded) {
138  QTimer::singleShot(0, this, [this]() {
139  if (focusProxy() && d->mCurrentWidget != focusProxy()) {
140  d->mCurrentWidget = focusProxy();
141  d->mCurrentWidget->installEventFilter(this);
142  }
143  });
144  }
145 
146  // Forward events to WebEngineView
147  if (obj == d->mCurrentWidget) {
148 #define HANDLE_EVENT(f, t) \
149  { \
150  bool wasAccepted = event->isAccepted(); \
151  event->setAccepted(false); \
152  f(static_cast<t *>(event)); \
153  bool ret = event->isAccepted(); \
154  event->setAccepted(wasAccepted); \
155  return ret; \
156  }
157 
158  switch (event->type()) {
159  case QEvent::KeyPress:
160  HANDLE_EVENT(forwardKeyPressEvent, QKeyEvent)
161  case QEvent::KeyRelease:
162  HANDLE_EVENT(forwardKeyReleaseEvent, QKeyEvent)
164  HANDLE_EVENT(forwardMousePressEvent, QMouseEvent)
166  HANDLE_EVENT(forwardMouseReleaseEvent, QMouseEvent)
167  case QEvent::MouseMove:
168  HANDLE_EVENT(forwardMouseMoveEvent, QMouseEvent)
169  case QEvent::Wheel:
170  HANDLE_EVENT(forwardWheelEvent, QWheelEvent)
171  default:
172  break;
173  }
174 
175 #undef HANDLE_EVENT
176  }
177  // Block already handled events
178  if (obj == this) {
179  switch (event->type()) {
180  case QEvent::KeyPress:
181  case QEvent::KeyRelease:
184  case QEvent::MouseMove:
185  case QEvent::Wheel:
186  return true;
187 
188  default:
189  break;
190  }
191  }
192  return QWebEngineView::eventFilter(obj, event);
193 }
194 
195 QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type)
196 {
197  Q_UNUSED(type)
198  delete d->mWebEngineNavigatorInterceptor;
199  delete d->mWebEngineNavigatorInterceptorView;
200  d->mWebEngineNavigatorInterceptorView = new WebEngineView();
201 
202  d->mWebEngineNavigatorInterceptor = new WebEngineNavigationRequestInterceptor(this->page());
203  d->mWebEngineNavigatorInterceptorView->setPage(d->mWebEngineNavigatorInterceptor);
204  return d->mWebEngineNavigatorInterceptorView;
205 }
206 
207 void WebEngineView::clearRelativePosition()
208 {
209  d->mSavedRelativePosition = -1;
210 }
211 
212 void WebEngineView::saveRelativePosition()
213 {
214  if (d->mSavedRelativePosition != -1) {
215  d->mSavedRelativePosition = page()->scrollPosition().toPoint().y();
216  }
217 }
218 
219 qreal WebEngineView::relativePosition() const
220 {
221  qCDebug(WEBENGINEVIEWER_LOG) << "Relative Position" << d->mSavedRelativePosition;
222  return d->mSavedRelativePosition;
223 }
224 
225 LocalDataBaseManager *WebEngineView::phishingDatabase() const
226 {
227  if (!d->mPhishingDatabase) {
228  d->mPhishingDatabase = new LocalDataBaseManager(const_cast<WebEngineView *>(this));
229  d->mPhishingDatabase->initialize();
230  }
231  return d->mPhishingDatabase;
232 }
The WebEngineView class.
Definition: webengineview.h:22
The LocalDataBaseManager class.
The WebEngineManageScript class.
Q_SCRIPTABLE CaptureState status()
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:19 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.