2 * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
6 * Privacy Browser PC is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser PC is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser PC. If not, see <http://www.gnu.org/licenses/>.
20 // Application headers.
21 #include "PrivacyWebEngineView.h"
23 #include "databases/CookiesDatabase.h"
24 #include "databases/DomainsDatabase.h"
25 #include "interceptors/UrlRequestInterceptor.h"
26 #include "windows/BrowserWindow.h"
28 // Qt toolkit headers.
29 #include <QContextMenuEvent>
32 // Construct the class.
33 PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr)
35 // Create an off-the-record profile (the default when no profile name is specified).
36 webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
38 // Create a WebEngine page.
39 QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
41 // Set the WebEngine page.
42 setPage(webEnginePagePointer);
44 // Get handles for the various aspects of the WebEngine.
45 webEngineSettingsPointer = webEnginePagePointer->settings();
47 // Instantiate the URL request interceptor.
48 UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
50 // Set the URL request interceptor.
51 webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
53 // Reapply the domain settings when the host changes.
54 connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(const QString&)), this, SLOT(applyDomainSettingsWithoutReloading(const QString&)));
56 // Display HTTP Ping blocked dialogs.
57 connect(urlRequestInterceptorPointer, SIGNAL(displayHttpPingDialog(const QString&)), this, SLOT(displayHttpPingDialog(const QString&)));
60 void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const
62 //qDebug() << "Add cookie: " << cookie.toRawForm();
64 // Add the new cookie to the list.
65 cookieListPointer->push_front(cookie);
67 // Update the cookie if it is durable and has new data.
68 if (CookiesDatabase::isUpdate(cookie))
69 CookiesDatabase::updateCookie(cookie);
71 // Update the cookies action.
72 emit updateCookiesAction(cookieListPointer->size());
75 void PrivacyWebEngineView::applyDomainSettingsWithoutReloading(const QString &hostname)
77 // Apply the domain settings `false` does not reload the website.
78 applyDomainSettings(hostname, false);
81 void PrivacyWebEngineView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
83 // Get the record for the hostname.
84 QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
86 // Check if the hostname has domain settings.
87 if (domainQuery.isValid()) // The hostname has domain settings.
89 // Get the domain record.
90 QSqlRecord domainRecord = domainQuery.record();
92 // Store the domain settings name.
93 domainSettingsName = domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString();
95 // Set the JavaScript status.
96 switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
98 // Set the default JavaScript status.
99 case (DomainsDatabase::SYSTEM_DEFAULT):
101 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
106 // Disable JavaScript.
107 case (DomainsDatabase::DISABLED):
109 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
114 // Enable JavaScript.
115 case (DomainsDatabase::ENABLED):
117 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
123 // Set the local storage status.
124 switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
126 // Set the default local storage status.
127 case (DomainsDatabase::SYSTEM_DEFAULT):
129 localStorageEnabled = Settings::localStorageEnabled();
134 // Disable local storage.
135 case (DomainsDatabase::DISABLED):
137 localStorageEnabled = false;
142 // Enable local storage.
143 case (DomainsDatabase::ENABLED):
145 localStorageEnabled = true;
151 // Set the DOM storage status.
152 switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
154 // Set the default DOM storage status. QWebEngineSettings confusingly calls this local storage.
155 case (DomainsDatabase::SYSTEM_DEFAULT):
157 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
162 // Disable DOM storage. QWebEngineSettings confusingly calls this local storage.
163 case (DomainsDatabase::DISABLED):
165 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
170 // Enable DOM storage. QWebEngineSettings confusingly calls this local storage.
171 case (DomainsDatabase::ENABLED):
173 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
179 // Set the user agent.
180 webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
182 // Check if a custom zoom factor is set.
183 if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
185 // Store the current zoom factor.
186 setZoomFactor(domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble());
190 // Reset the current zoom factor.
191 setZoomFactor(Settings::zoomFactor());
194 else // The hostname does not have domain settings.
196 // Reset the domain settings name.
197 domainSettingsName = QLatin1String("");
199 // Set the JavaScript status.
200 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
202 // Set the local storage status.
203 localStorageEnabled = Settings::localStorageEnabled();
205 // Set DOM storage. In QWebEngineSettings it is called Local Storage.
206 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
208 // Set the user agent.
209 webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
211 // Set the zoom factor.
212 setZoomFactor(Settings::zoomFactor());
215 // Reload the website if requested.
223 void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) {
224 // Get a handle for the
225 QWebEnginePage *webEnginePagePointer = page();
227 // Get a handle for the menu.
228 QMenu *contextMenu = webEnginePagePointer->createStandardContextMenu();
230 // Get the list of context menu actions.
231 const QList<QAction *> contextMenuActionsList = contextMenu->actions();
233 // Add the open link in new background tab action if the context menu already contains the open link in new window action.
234 if (contextMenuActionsList.contains(webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow)))
236 // Move the open in new tab action to the top of the list.
237 contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewTab));
239 // Add the open link in background tab action below the open in new tab action.
240 contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewBackgroundTab));
242 // Move the open in new window action below the open in background tab action.
243 contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow));
245 // Add a separator below the open in new window action.
246 contextMenu->insertSeparator(webEnginePagePointer->action(QWebEnginePage::Back));
249 // Display the menu using the location in the context menu event.
250 contextMenu->popup(contextMenuEvent->globalPos());
253 QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType webWindowType) {
254 // Get a handle for the browser window.
255 BrowserWindow *browserWindowPointer = qobject_cast<BrowserWindow*>(window());
257 // Create the requested window type.
258 switch (webWindowType)
260 case QWebEnginePage::WebBrowserTab:
262 // Create the new tab and return the privacy WebEngine view pointer. `true` removes the focus from the blank URL line edit.
263 // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
264 return browserWindowPointer->tabWidgetPointer->addTab(true);
267 case QWebEnginePage::WebBrowserWindow:
269 // Create a new browser window.
270 BrowserWindow *newBrowserWindowPointer = new BrowserWindow();
272 // Show the new browser window.
273 newBrowserWindowPointer->show();
275 // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
276 return newBrowserWindowPointer->tabWidgetPointer->loadBlankInitialWebsite();
279 case QWebEnginePage::WebBrowserBackgroundTab:
281 // Create the new tab and return the privacy WebEngine view pointer. `false` does not clear the URL line edit. `true` creates a background tab.
282 // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
283 return browserWindowPointer->tabWidgetPointer->addTab(false, true);
288 // Return a null pointer for opening a web dialog.
294 void PrivacyWebEngineView::displayHttpPingDialog(const QString &httpPingUrl) const
296 // Display the HTTP Ping blocked dialog.
297 emit displayHttpPingBlockedDialog(httpPingUrl);
300 void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
302 //qDebug() << "Remove cookie: " << cookie.toRawForm();
304 // Remove the cookie from the list.
305 cookieListPointer->remove(cookie);
307 // Update the cookies action.
308 emit updateCookiesAction(cookieListPointer->size());