1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2015 - 2021 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19 
20 #ifndef OTTER_QTWEBENGINEWEBWIDGET_H
21 #define OTTER_QTWEBENGINEWEBWIDGET_H
22 
23 #include "../../../../ui/WebWidget.h"
24 
25 #include <QtNetwork/QNetworkReply>
26 #include <QtWebEngineCore/QtWebEngineCoreVersion>
27 #include <QtWebEngineWidgets/QWebEngineFullScreenRequest>
28 #include <QtWebEngineWidgets/QWebEngineView>
29 
30 namespace Otter
31 {
32 
33 class QtWebEnginePage;
34 class QtWebEngineUrlRequestInterceptor;
35 class SourceViewerWebWidget;
36 
37 #if QTWEBENGINECORE_VERSION >= 0x050B00
38 class QtWebEngineInspectorWidget final : public QWebEngineView
39 {
40 public:
41 	explicit QtWebEngineInspectorWidget(QWebEnginePage *page, QWidget *parent);
42 
43 protected:
44 	void showEvent(QShowEvent *event) override;
45 
46 private:
47 	QWebEnginePage *m_page;
48 };
49 #endif
50 
51 class QtWebEngineWebWidget final : public WebWidget
52 {
53 	Q_OBJECT
54 
55 public:
56 	struct QtWebEngineHitTestResult final : public HitTestResult
57 	{
QtWebEngineHitTestResultfinal58 		explicit QtWebEngineHitTestResult(const QVariant &result)
59 		{
60 			const QVariantMap map(result.toMap());
61 			const QVariantMap geometryMap(map.value(QLatin1String("geometry")).toMap());
62 
63 			title = map.value(QLatin1String("title")).toString();
64 			tagName = map.value(QLatin1String("tagName")).toString();
65 			alternateText = map.value(QLatin1String("alternateText")).toString();
66 			longDescription = map.value(QLatin1String("longDescription")).toString();
67 			formUrl = QUrl(map.value(QLatin1String("formUrl")).toString());
68 			frameUrl = QUrl(map.value(QLatin1String("frameUrl")).toString());
69 			imageUrl = QUrl(map.value(QLatin1String("imageUrl")).toString());
70 			linkUrl = QUrl(map.value(QLatin1String("linkUrl")).toString());
71 			mediaUrl = QUrl(map.value(QLatin1String("mediaUrl")).toString());
72 			elementGeometry = QRect(geometryMap.value(QLatin1String("x")).toInt(), geometryMap.value(QLatin1String("y")).toInt(), geometryMap.value(QLatin1String("w")).toInt(), geometryMap.value(QLatin1String("h")).toInt());
73 			hitPosition = map.value(QLatin1String("position")).toPoint();
74 			playbackRate = map.value(QLatin1String("playbackRate")).toReal();
75 			flags = static_cast<HitTestFlags>(map.value(QLatin1String("flags")).toInt());
76 		}
77 	};
78 
79 	~QtWebEngineWebWidget();
80 
81 	void search(const QString &query, const QString &searchEngine) override;
82 	void print(QPrinter *printer) override;
83 	WebWidget* clone(bool cloneHistory = true, bool isPrivate = false, const QStringList &excludedOptions = {}) const override;
84 #if QTWEBENGINECORE_VERSION >= 0x050B00
85 	QWidget* getInspector() override;
86 #endif
87 	QWidget* getViewport() override;
88 	QString getTitle() const override;
89 	QString getDescription() const override;
90 	QString getActiveStyleSheet() const override;
91 	QString getSelectedText() const override;
92 	QVariant getPageInformation(PageInformation key) const override;
93 	QUrl getUrl() const override;
94 	QIcon getIcon() const override;
95 	QPoint getScrollPosition() const override;
96 	LinkUrl getActiveFrame() const override;
97 	LinkUrl getActiveImage() const override;
98 	LinkUrl getActiveLink() const override;
99 	LinkUrl getActiveMedia() const override;
100 	WindowHistoryInformation getHistory() const override;
101 	HitTestResult getHitTestResult(const QPoint &position) override;
102 	QStringList getStyleSheets() const override;
103 	QVector<LinkUrl> getFeeds() const override;
104 	QVector<LinkUrl> getLinks() const override;
105 	QVector<LinkUrl> getSearchEngines() const override;
106 #if QTWEBENGINECORE_VERSION >= 0x050D00
107 	QVector<NetworkManager::ResourceInformation> getBlockedRequests() const override;
108 #endif
109 	QMultiMap<QString, QString> getMetaData() const override;
110 	LoadingState getLoadingState() const override;
111 	int getZoom() const override;
112 	int findInPage(const QString &text, FindFlags flags = NoFlagsFind) override;
113 	bool hasSelection() const override;
114 	bool hasWatchedChanges(ChangeWatcher watcher) const override;
115 	bool isAudible() const override;
116 	bool isAudioMuted() const override;
117 	bool isFullScreen() const override;
118 	bool isPrivate() const override;
119 	bool eventFilter(QObject *object, QEvent *event) override;
120 
121 public slots:
122 	void clearOptions() override;
123 	void triggerAction(int identifier, const QVariantMap &parameters = {}, ActionsManager::TriggerType trigger = ActionsManager::UnknownTrigger) override;
124 	void setActiveStyleSheet(const QString &styleSheet) override;
125 	void setPermission(FeaturePermission feature, const QUrl &url, PermissionPolicies policies) override;
126 	void setOption(int identifier, const QVariant &value) override;
127 	void setScrollPosition(const QPoint &position) override;
128 	void setHistory(const WindowHistoryInformation &history) override;
129 	void setZoom(int zoom) override;
130 	void setUrl(const QUrl &url, bool isTyped = true) override;
131 
132 protected:
133 	explicit QtWebEngineWebWidget(const QVariantMap &parameters, WebBackend *backend, ContentsWidget *parent = nullptr);
134 
135 	void timerEvent(QTimerEvent *event) override;
136 	void showEvent(QShowEvent *event) override;
137 	void hideEvent(QHideEvent *event) override;
138 	void focusInEvent(QFocusEvent *event) override;
139 	void ensureInitialized();
140 	void notifyWatchedDataChanged(ChangeWatcher watcher);
141 	void updateOptions(const QUrl &url);
142 	void updateWatchedData(ChangeWatcher watcher) override;
143 	void setHistory(QDataStream &stream);
144 	void setOptions(const QHash<int, QVariant> &options, const QStringList &excludedOptions = {}) override;
145 	QWebEnginePage* getPage() const;
146 	QString parsePosition(const QString &script, const QPoint &position) const;
147 	QDateTime getLastUrlClickTime() const;
148 #if QTWEBENGINECORE_VERSION >= 0x050D00
149 	QStringList getBlockedElements() const;
150 #endif
151 	QVector<LinkUrl> processLinks(const QVariantList &rawLinks) const;
152 	bool canGoBack() const override;
153 	bool canGoForward() const override;
154 	bool canFastForward() const override;
155 #if QTWEBENGINECORE_VERSION >= 0x050B00
156 	bool canInspect() const override;
157 #endif
158 	bool canRedo() const override;
159 	bool canUndo() const override;
160 	bool canShowContextMenu(const QPoint &position) const override;
161 	bool canViewSource() const override;
162 #if QTWEBENGINECORE_VERSION >= 0x050B00
163 	bool isInspecting() const override;
164 #endif
165 	bool isPopup() const override;
166 	bool isScrollBar(const QPoint &position) const override;
167 	bool isTypedIn() const;
168 
169 protected slots:
170 	void handleLoadStarted();
171 	void handleLoadFinished();
172 	void handleViewSourceReplyFinished();
173 #if QTWEBENGINECORE_VERSION >= 0x050C00
174 	void handlePrintRequest();
175 #endif
176 	void handleAuthenticationRequired(const QUrl &url, QAuthenticator *authenticator);
177 	void handleProxyAuthenticationRequired(const QUrl &url, QAuthenticator *authenticator, const QString &proxy);
178 	void handleFullScreenRequest(QWebEngineFullScreenRequest request);
179 	void notifyTitleChanged();
180 	void notifyUrlChanged();
181 	void notifyIconChanged();
182 	void notifyPermissionRequested(const QUrl &url, QWebEnginePage::Feature nativeFeature, bool cancel);
183 	void notifyRenderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus status);
184 	void notifyNavigationActionsChanged();
185 
186 private:
187 	QWebEngineView *m_webView;
188 #if QTWEBENGINECORE_VERSION >= 0x050B00
189 	QWebEngineView *m_inspectorWidget;
190 #endif
191 	QtWebEnginePage *m_page;
192 #if QTWEBENGINECORE_VERSION >= 0x050D00
193 	QtWebEngineUrlRequestInterceptor *m_requestInterceptor;
194 #endif
195 	QDateTime m_lastUrlClickTime;
196 	HitTestResult m_hitResult;
197 	QHash<QNetworkReply*, QPointer<SourceViewerWebWidget> > m_viewSourceReplies;
198 	QMultiMap<QString, QString> m_metaData;
199 	QStringList m_styleSheets;
200 	QVector<LinkUrl> m_feeds;
201 	QVector<LinkUrl> m_links;
202 	QVector<LinkUrl> m_searchEngines;
203 	QVector<bool> m_watchedChanges;
204 	LoadingState m_loadingState;
205 	TrileanValue m_canGoForwardValue;
206 	int m_documentLoadingProgress;
207 	int m_focusProxyTimer;
208 	int m_updateNavigationActionsTimer;
209 	bool m_isClosing;
210 	bool m_isEditing;
211 	bool m_isFullScreen;
212 	bool m_isTypedIn;
213 
214 friend class QtWebEnginePage;
215 friend class QtWebEngineWebBackend;
216 };
217 
218 }
219 
220 #endif
221