Messagelib

webengineview.cpp
1 /*
2  SPDX-FileCopyrightText: 2016-2021 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::addScript(const QString &source, const QString &scriptName, QWebEngineScript::InjectionPoint injectionPoint)
100 {
101  d->mManagerScript->addScript(page()->profile(), source, scriptName, injectionPoint);
102 }
103 
104 void WebEngineView::forwardWheelEvent(QWheelEvent *event)
105 {
106  Q_UNUSED(event)
107 }
108 
109 void WebEngineView::forwardKeyPressEvent(QKeyEvent *event)
110 {
111  Q_UNUSED(event)
112 }
113 
114 void WebEngineView::forwardKeyReleaseEvent(QKeyEvent *event)
115 {
116  Q_UNUSED(event)
117 }
118 
119 void WebEngineView::forwardMousePressEvent(QMouseEvent *event)
120 {
121  Q_UNUSED(event)
122 }
123 
124 void WebEngineView::forwardMouseMoveEvent(QMouseEvent *event)
125 {
126  Q_UNUSED(event)
127 }
128 
129 void WebEngineView::forwardMouseReleaseEvent(QMouseEvent *event)
130 {
131  Q_UNUSED(event)
132 }
133 
134 bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
135 {
136  // Keyboard events are sent to parent widget
137  if (obj == this && event->type() == QEvent::ParentChange && parentWidget()) {
138  parentWidget()->installEventFilter(this);
139  }
140 
141  // Hack to find widget that receives input events
142  if (obj == this && event->type() == QEvent::ChildAdded) {
143  QTimer::singleShot(0, this, [this]() {
144  if (focusProxy() && d->mCurrentWidget != focusProxy()) {
145  d->mCurrentWidget = focusProxy();
146  d->mCurrentWidget->installEventFilter(this);
147  }
148  });
149  }
150 
151  // Forward events to WebEngineView
152  if (obj == d->mCurrentWidget) {
153 #define HANDLE_EVENT(f, t) \
154  { \
155  bool wasAccepted = event->isAccepted(); \
156  event->setAccepted(false); \
157  f(static_cast<t *>(event)); \
158  bool ret = event->isAccepted(); \
159  event->setAccepted(wasAccepted); \
160  return ret; \
161  }
162 
163  switch (event->type()) {
164  case QEvent::KeyPress:
165  HANDLE_EVENT(forwardKeyPressEvent, QKeyEvent)
166  case QEvent::KeyRelease:
167  HANDLE_EVENT(forwardKeyReleaseEvent, QKeyEvent)
168  case QEvent::MouseButtonPress:
169  HANDLE_EVENT(forwardMousePressEvent, QMouseEvent)
170  case QEvent::MouseButtonRelease:
171  HANDLE_EVENT(forwardMouseReleaseEvent, QMouseEvent)
172  case QEvent::MouseMove:
173  HANDLE_EVENT(forwardMouseMoveEvent, QMouseEvent)
174  case QEvent::Wheel:
175  HANDLE_EVENT(forwardWheelEvent, QWheelEvent)
176  default:
177  break;
178  }
179 
180 #undef HANDLE_EVENT
181  }
182  // Block already handled events
183  if (obj == this) {
184  switch (event->type()) {
185  case QEvent::KeyPress:
186  case QEvent::KeyRelease:
189  case QEvent::MouseMove:
190  case QEvent::Wheel:
191  return true;
192 
193  default:
194  break;
195  }
196  }
197  return QWebEngineView::eventFilter(obj, event);
198 }
199 
200 QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type)
201 {
202  Q_UNUSED(type)
203  delete d->mWebEngineNavigatorInterceptor;
204  delete d->mWebEngineNavigatorInterceptorView;
205  d->mWebEngineNavigatorInterceptorView = new WebEngineView();
206 
207  d->mWebEngineNavigatorInterceptor = new WebEngineNavigationRequestInterceptor(this->page());
208  d->mWebEngineNavigatorInterceptorView->setPage(d->mWebEngineNavigatorInterceptor);
209  return d->mWebEngineNavigatorInterceptorView;
210 }
211 
212 void WebEngineView::clearRelativePosition()
213 {
214  d->mSavedRelativePosition = -1;
215 }
216 
217 void WebEngineView::saveRelativePosition()
218 {
219  if (d->mSavedRelativePosition != -1) {
220  d->mSavedRelativePosition = page()->scrollPosition().toPoint().y();
221  }
222 }
223 
224 qreal WebEngineView::relativePosition() const
225 {
226  qCDebug(WEBENGINEVIEWER_LOG) << "Relative Position" << d->mSavedRelativePosition;
227  return d->mSavedRelativePosition;
228 }
229 
230 LocalDataBaseManager *WebEngineView::phishingDatabase() const
231 {
232  if (!d->mPhishingDatabase) {
233  d->mPhishingDatabase = new LocalDataBaseManager(const_cast<WebEngineView *>(this));
234  d->mPhishingDatabase->initialize();
235  }
236  return d->mPhishingDatabase;
237 }
QEvent::Type type() const const
The LocalDataBaseManager class.
The WebEngineManageScript class.
The WebEngineView class.
Definition: webengineview.h:23
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Dec 4 2021 23:12:55 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.