1 /*
2 SPDX-FileCopyrightText: 2016-2021 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "akrwebengineviewer.h"
8 #include "articleviewer-ng/webengine/articleviewerwebenginepage.h"
9
10 #include "actionmanager.h"
11 #include "actions.h"
12 #include "akregatorconfig.h"
13 #include "webengine/urlhandlerwebenginemanager.h"
14
15 #include <KActionCollection>
16 #include <KActionMenu>
17 #include <KIO/KUriFilterSearchProviderActions>
18 #include <KPIMTextEdit/TextToSpeech>
19 #include <QContextMenuEvent>
20 #include <QMenu>
21 #include <QWebEngineHistory>
22 #include <QWebEngineSettings>
23 #include <WebEngineViewer/BlockExternalResourcesUrlInterceptor>
24 #include <WebEngineViewer/InterceptorManager>
25 #include <WebEngineViewer/LoadExternalReferencesUrlInterceptor>
26 #include <WebEngineViewer/WebHitTest>
27 #include <WebEngineViewer/WebHitTestResult>
28
29 using namespace Akregator;
30
AkrWebEngineViewer(KActionCollection * ac,QWidget * parent)31 AkrWebEngineViewer::AkrWebEngineViewer(KActionCollection *ac, QWidget *parent)
32 : ArticleViewerWebEngine(ac, parent)
33 {
34 if (mExternalReference) {
35 mExternalReference->setAllowExternalContent(true);
36 }
37 if (mBlockExternalReference) { // Don't block element
38 mBlockExternalReference->setEnabled(false);
39 }
40 // TODO update settings when we change config
41 settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::enableJavascript());
42 settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false);
43 settings()->setAttribute(QWebEngineSettings::AutoLoadImages, true);
44 settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
45 settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, false);
46 settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
47 settings()->setAttribute(QWebEngineSettings::XSSAuditingEnabled, false);
48 settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
49 settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false);
50 // settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false);
51
52 settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false);
53 }
54
~AkrWebEngineViewer()55 AkrWebEngineViewer::~AkrWebEngineViewer()
56 {
57 }
58
updateSecurity()59 void AkrWebEngineViewer::updateSecurity()
60 {
61 // Nothing
62 }
63
contextMenuEvent(QContextMenuEvent * e)64 void AkrWebEngineViewer::contextMenuEvent(QContextMenuEvent *e)
65 {
66 displayContextMenu(e->pos());
67 }
68
slotWebHitFinished(const WebEngineViewer::WebHitTestResult & result)69 void AkrWebEngineViewer::slotWebHitFinished(const WebEngineViewer::WebHitTestResult &result)
70 {
71 mCurrentUrl = result.linkUrl();
72 if (URLHandlerWebEngineManager::instance()->handleContextMenuRequest(mCurrentUrl, mapToGlobal(result.pos()), this)) {
73 return;
74 }
75 QMenu popup(this);
76 QWebEngineHistory *history = page()->history();
77 bool needSeparator = false;
78 if (history->canGoBack()) {
79 popup.addAction(pageAction(QWebEnginePage::Back));
80 needSeparator = true;
81 }
82
83 if (history->canGoForward()) {
84 popup.addAction(pageAction(QWebEnginePage::Forward));
85 needSeparator = true;
86 }
87 if (needSeparator) {
88 popup.addSeparator();
89 }
90 popup.addAction(pageAction(QWebEnginePage::Stop));
91 popup.addSeparator();
92 popup.addAction(pageAction(QWebEnginePage::Reload));
93 popup.addSeparator();
94
95 const bool noContentSelected = selectedText().isEmpty();
96 if (noContentSelected) {
97 if (!mCurrentUrl.isEmpty()) {
98 {
99 QAction *act = createOpenLinkInNewTabAction(mCurrentUrl, &popup);
100 connect(act, &QAction::triggered, this, &AkrWebEngineViewer::slotOpenLinkInBackgroundTab);
101 popup.addAction(act);
102 }
103 {
104 QAction *act = createOpenLinkInExternalBrowserAction(mCurrentUrl, &popup);
105 connect(act, &QAction::triggered, this, &AkrWebEngineViewer::slotOpenLinkInBrowser);
106 popup.addAction(act);
107 }
108 popup.addSeparator();
109 popup.addAction(mActionCollection->action(QStringLiteral("savelinkas")));
110 popup.addAction(mActionCollection->action(QStringLiteral("copylinkaddress")));
111 }
112 if (!result.imageUrl().isEmpty()) {
113 popup.addSeparator();
114 popup.addAction(mActionCollection->action(QStringLiteral("copy_image_location")));
115 popup.addAction(mActionCollection->action(QStringLiteral("saveas_imageurl")));
116 }
117 popup.addSeparator();
118 popup.addActions(viewerPluginActionList(MessageViewer::ViewerPluginInterface::NeedUrl));
119 popup.addSeparator();
120 popup.addAction(mShareServiceManager->menu());
121 } else {
122 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_copy")));
123 popup.addSeparator();
124 mWebShortcutMenuManager->setSelectedText(page()->selectedText());
125 mWebShortcutMenuManager->addWebShortcutsToMenu(&popup);
126 popup.addSeparator();
127 popup.addActions(viewerPluginActionList(MessageViewer::ViewerPluginInterface::NeedSelection));
128 }
129 popup.addSeparator();
130 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_print")));
131 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("viewer_printpreview")));
132 popup.addSeparator();
133 popup.addAction(pageAction(QWebEnginePage::SavePage));
134 popup.addSeparator();
135 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("tab_mute")));
136 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("tab_unmute")));
137 const QList<QAction *> interceptorUrlActions = mNetworkAccessManager->interceptorUrlActions(result);
138 if (!interceptorUrlActions.isEmpty()) {
139 popup.addSeparator();
140 popup.addActions(interceptorUrlActions);
141 }
142 popup.addSeparator();
143 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("find_in_messages")));
144 if (KPIMTextEdit::TextToSpeech::self()->isReady()) {
145 popup.addSeparator();
146 popup.addAction(ActionManager::getInstance()->action(QStringLiteral("speak_text")));
147 }
148 popup.exec(mapToGlobal(result.pos()));
149 }
150
displayContextMenu(const QPoint & pos)151 void AkrWebEngineViewer::displayContextMenu(const QPoint &pos)
152 {
153 WebEngineViewer::WebHitTest *webHit = mPageEngine->hitTestContent(pos);
154 connect(webHit, &WebEngineViewer::WebHitTest::finished, this, &AkrWebEngineViewer::slotWebHitFinished);
155 }
156
createWindow(QWebEnginePage::WebWindowType type)157 QWebEngineView *AkrWebEngineViewer::createWindow(QWebEnginePage::WebWindowType type)
158 {
159 Q_UNUSED(type)
160 return this;
161 }
162