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 "webenginenavigationrequestinterceptor.h"
9 #include "webenginemanagescript.h"
10 #include "webengineviewer_debug.h"
11 #include "checkphishingurl/localdatabasemanager.h"
12 #include <QEvent>
13 #include <QKeyEvent>
14 #include <QMouseEvent>
15 #include <QWheelEvent>
16 #include <QTimer>
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,
82  this, [this](QWebEnginePage::RenderProcessTerminationStatus status) {
83  d->renderProcessTerminated(status);
84  });
85  connect(this, &QWebEngineView::loadFinished,
86  this, [this]() {
87  // Reset the crash counter if we manage to actually load a page.
88  // This does not perfectly correspond to "we managed to render
89  // a page", but it's the best we have
90  d->mCrashCount = 0;
91  });
92 }
93 
94 WebEngineView::~WebEngineView()
95 {
96  delete d;
97 }
98 
99 WebEngineManageScript *WebEngineView::webEngineManagerScript() const
100 {
101  return d->mManagerScript;
102 }
103 
104 void WebEngineView::addScript(const QString &source, const QString &scriptName, QWebEngineScript::InjectionPoint injectionPoint)
105 {
106  d->mManagerScript->addScript(page()->profile(), source, scriptName, injectionPoint);
107 }
108 
109 void WebEngineView::forwardWheelEvent(QWheelEvent *event)
110 {
111  Q_UNUSED(event)
112 }
113 
114 void WebEngineView::forwardKeyPressEvent(QKeyEvent *event)
115 {
116  Q_UNUSED(event)
117 }
118 
119 void WebEngineView::forwardKeyReleaseEvent(QKeyEvent *event)
120 {
121  Q_UNUSED(event)
122 }
123 
124 void WebEngineView::forwardMousePressEvent(QMouseEvent *event)
125 {
126  Q_UNUSED(event)
127 }
128 
129 void WebEngineView::forwardMouseMoveEvent(QMouseEvent *event)
130 {
131  Q_UNUSED(event)
132 }
133 
134 void WebEngineView::forwardMouseReleaseEvent(QMouseEvent *event)
135 {
136  Q_UNUSED(event)
137 }
138 
139 bool WebEngineView::eventFilter(QObject *obj, QEvent *event)
140 {
141  // Keyboard events are sent to parent widget
142  if (obj == this && event->type() == QEvent::ParentChange && parentWidget()) {
143  parentWidget()->installEventFilter(this);
144  }
145 
146  // Hack to find widget that receives input events
147  if (obj == this && event->type() == QEvent::ChildAdded) {
148  QTimer::singleShot(0, this, [this]() {
149  if (focusProxy() && d->mCurrentWidget != focusProxy()) {
150  d->mCurrentWidget = focusProxy();
151  d->mCurrentWidget->installEventFilter(this);
152  }
153  });
154  }
155 
156  // Forward events to WebEngineView
157  if (obj == d->mCurrentWidget) {
158 #define HANDLE_EVENT(f, t) \
159  { \
160  bool wasAccepted = event->isAccepted(); \
161  event->setAccepted(false); \
162  f(static_cast<t *>(event)); \
163  bool ret = event->isAccepted(); \
164  event->setAccepted(wasAccepted); \
165  return ret; \
166  }
167 
168  switch (event->type()) {
169  case QEvent::KeyPress:
170  HANDLE_EVENT(forwardKeyPressEvent, QKeyEvent);
171  case QEvent::KeyRelease:
172  HANDLE_EVENT(forwardKeyReleaseEvent, QKeyEvent);
174  HANDLE_EVENT(forwardMousePressEvent, QMouseEvent);
176  HANDLE_EVENT(forwardMouseReleaseEvent, QMouseEvent);
177  case QEvent::MouseMove:
178  HANDLE_EVENT(forwardMouseMoveEvent, QMouseEvent);
179  case QEvent::Wheel:
180  HANDLE_EVENT(forwardWheelEvent, QWheelEvent);
181  default:
182  break;
183  }
184 
185 #undef HANDLE_EVENT
186  }
187  // Block already handled events
188  if (obj == this) {
189  switch (event->type()) {
190  case QEvent::KeyPress:
191  case QEvent::KeyRelease:
194  case QEvent::MouseMove:
195  case QEvent::Wheel:
196  return true;
197 
198  default:
199  break;
200  }
201  }
202  return QWebEngineView::eventFilter(obj, event);
203 }
204 
205 QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type)
206 {
207  Q_UNUSED(type)
208  delete d->mWebEngineNavigatorInterceptor;
209  delete d->mWebEngineNavigatorInterceptorView;
210  d->mWebEngineNavigatorInterceptorView = new WebEngineView();
211 
212  d->mWebEngineNavigatorInterceptor = new WebEngineNavigationRequestInterceptor(this->page());
213  d->mWebEngineNavigatorInterceptorView->setPage(d->mWebEngineNavigatorInterceptor);
214  return d->mWebEngineNavigatorInterceptorView;
215 }
216 
217 void WebEngineView::clearRelativePosition()
218 {
219  d->mSavedRelativePosition = -1;
220 }
221 
222 void WebEngineView::saveRelativePosition()
223 {
224  if (d->mSavedRelativePosition != -1) {
225  d->mSavedRelativePosition = page()->scrollPosition().toPoint().y();
226  }
227 }
228 
229 qreal WebEngineView::relativePosition() const
230 {
231  qCDebug(WEBENGINEVIEWER_LOG) << "Relative Position" << d->mSavedRelativePosition;
232  return d->mSavedRelativePosition;
233 }
234 
235 LocalDataBaseManager *WebEngineView::phishingDatabase() const
236 {
237  if (!d->mPhishingDatabase) {
238  d->mPhishingDatabase = new LocalDataBaseManager(const_cast<WebEngineView *>(this));
239  d->mPhishingDatabase->initialize();
240  }
241  return d->mPhishingDatabase;
242 }
QEvent::Type type() const const
The LocalDataBaseManager class.
The WebEngineManageScript class.
The WebEngineView class.
Definition: webengineview.h:22
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Jan 20 2021 23:19:55 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.