/*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
*
* This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
*
// Application headers.
#include "PrivacyWebEngineView.h"
+#include "Settings.h"
#include "databases/CookiesDatabase.h"
+#include "databases/DomainsDatabase.h"
+#include "interceptors/UrlRequestInterceptor.h"
#include "windows/BrowserWindow.h"
+// Qt toolkit headers.
+#include <QContextMenuEvent>
+#include <QMenu>
+
// Construct the class.
-PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr) {}
+PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr)
+{
+ // Create an off-the-record profile (the default when no profile name is specified).
+ webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
+
+ // Create a WebEngine page.
+ QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
+
+ // Set the WebEngine page.
+ setPage(webEnginePagePointer);
+
+ // Get handles for the various aspects of the WebEngine.
+ webEngineSettingsPointer = webEnginePagePointer->settings();
+
+ // Instantiate the URL request interceptor.
+ UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
+
+ // Set the URL request interceptor.
+ webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
+
+ // Reapply the domain settings when the host changes.
+ connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(const QString&)), this, SLOT(applyDomainSettingsWithoutReloading(const QString&)));
+
+ // Display HTTP Ping blocked dialogs.
+ connect(urlRequestInterceptorPointer, SIGNAL(displayHttpPingDialog(const QString&)), this, SLOT(displayHttpPingDialog(const QString&)));
+}
void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const
{
emit updateCookiesAction(cookieListPointer->size());
}
-QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType webWindowType) {
- qDebug().noquote().nospace() << "Web window type: " << webWindowType;
+void PrivacyWebEngineView::applyDomainSettingsWithoutReloading(const QString &hostname)
+{
+ // Apply the domain settings `false` does not reload the website.
+ applyDomainSettings(hostname, false);
+}
+
+void PrivacyWebEngineView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
+{
+ // Get the record for the hostname.
+ QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
+
+ // Check if the hostname has domain settings.
+ if (domainQuery.isValid()) // The hostname has domain settings.
+ {
+ // Store the domain settings name.
+ domainSettingsName = domainQuery.value(DomainsDatabase::DOMAIN_NAME).toString();
+
+ // Set the JavaScript status.
+ switch (domainQuery.value(DomainsDatabase::JAVASCRIPT).toInt())
+ {
+ // Set the default JavaScript status.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
+
+ break;
+ }
+
+ // Enable JavaScript.
+ case (DomainsDatabase::ENABLED):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+
+ break;
+ }
+
+ // Disable JavaScript.
+ case (DomainsDatabase::DISABLED):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
+ break;
+ }
+ }
+
+ // Set the local storage status.
+ switch (domainQuery.value(DomainsDatabase::LOCAL_STORAGE).toInt())
+ {
+ // Set the default local storage status.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ localStorageEnabled = Settings::localStorageEnabled();
+
+ break;
+ }
+
+ // Enable local storage.
+ case (DomainsDatabase::ENABLED):
+ {
+ localStorageEnabled = true;
+
+ break;
+ }
+
+ // Disable local storage.
+ case (DomainsDatabase::DISABLED):
+ {
+ localStorageEnabled = false;
+
+ break;
+ }
+ }
+
+ // Set the DOM storage status.
+ switch (domainQuery.value(DomainsDatabase::DOM_STORAGE).toInt())
+ {
+ // Set the default DOM storage status. QWebEngineSettings confusingly calls this local storage.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
+
+ break;
+ }
+
+ // Enable DOM storage. QWebEngineSettings confusingly calls this local storage.
+ case (DomainsDatabase::ENABLED):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
+
+ break;
+ }
+
+ // Disable DOM storage. QWebEngineSettings confusingly calls this local storage.
+ case (DomainsDatabase::DISABLED):
+ {
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
+
+ break;
+ }
+ }
+ // Set the user agent.
+ webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainQuery.value(DomainsDatabase::USER_AGENT).toString()));
+
+ // Check if a custom zoom factor is set.
+ if (domainQuery.value(DomainsDatabase::ZOOM_FACTOR).toInt())
+ {
+ // Store the current zoom factor.
+ defaultZoomFactor = domainQuery.value(DomainsDatabase::CUSTOM_ZOOM_FACTOR).toDouble();
+ }
+ else
+ {
+ // Store the current zoom factor.
+ defaultZoomFactor = Settings::zoomFactor();
+ }
+ }
+ else // The hostname does not have domain settings.
+ {
+ // Reset the domain settings name.
+ domainSettingsName = QLatin1String("");
+
+ // Set the JavaScript status.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
+
+ // Set the local storage status.
+ localStorageEnabled = Settings::localStorageEnabled();
+
+ // Set DOM storage. In QWebEngineSettings it is called Local Storage.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
+
+ // Set the user agent.
+ webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
+
+ // Store the zoom factor.
+ defaultZoomFactor = Settings::zoomFactor();
+ }
+
+ // Set the current zoom factor.
+ setZoomFactor(defaultZoomFactor);
+
+ // Reload the website if requested.
+ if (reloadWebsite)
+ reload();
+
+ // Update the UI.
+ emit updateUi(this);
+}
+
+void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) {
+ // Get a handle for the
+ QWebEnginePage *webEnginePagePointer = page();
+
+ // Get a handle for the menu.
+ QMenu *contextMenu = webEnginePagePointer->createStandardContextMenu();
+
+ // Get the list of context menu actions.
+ const QList<QAction *> contextMenuActionsList = contextMenu->actions();
+
+ // Add the open link in new background tab action if the context menu already contains the open link in new window action.
+ if (contextMenuActionsList.contains(webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow)))
+ {
+ // Move the open in new tab action to the top of the list.
+ contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewTab));
+
+ // Add the open link in background tab action below the open in new tab action.
+ contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewBackgroundTab));
+
+ // Move the open in new window action below the open in background tab action.
+ contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow));
+
+ // Add a separator below the open in new window action.
+ contextMenu->insertSeparator(webEnginePagePointer->action(QWebEnginePage::Back));
+ }
+
+ // Display the menu using the location in the context menu event.
+ contextMenu->popup(contextMenuEvent->globalPos());
+}
+
+QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType webWindowType) {
// Get a handle for the browser window.
BrowserWindow *browserWindowPointer = qobject_cast<BrowserWindow*>(window());
- // Create the requsted window type.
- switch (webWindowType) {
- case QWebEnginePage::WebBrowserTab: {
+ // Create the requested window type.
+ switch (webWindowType)
+ {
+ case QWebEnginePage::WebBrowserTab:
+ {
// Create the new tab and return the privacy WebEngine view pointer. `true` removes the focus from the blank URL line edit.
// The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
return browserWindowPointer->tabWidgetPointer->addTab(true);
}
- default: {
- // Return an null pointer.
+ case QWebEnginePage::WebBrowserWindow:
+ {
+ // Create a new browser window.
+ BrowserWindow *newBrowserWindowPointer = new BrowserWindow();
+
+ // Show the new browser window.
+ newBrowserWindowPointer->show();
+
+ // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
+ return newBrowserWindowPointer->tabWidgetPointer->loadBlankInitialWebsite();
+ }
+
+ case QWebEnginePage::WebBrowserBackgroundTab:
+ {
+ // Create the new tab and return the privacy WebEngine view pointer. `false` does not clear the URL line edit. `true` creates a background tab.
+ // The new privacy WebEngine view pointer is returned so it can be populated with the link from the context menu.
+ return browserWindowPointer->tabWidgetPointer->addTab(false, true);
+ }
+
+ default:
+ {
+ // Return a null pointer for opening a web dialog.
return nullptr;
}
}
}
+void PrivacyWebEngineView::displayHttpPingDialog(const QString &httpPingUrl) const
+{
+ // Display the HTTP Ping blocked dialog.
+ emit displayHttpPingBlockedDialog(httpPingUrl);
+}
+
void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
{
//qDebug() << "Remove cookie: " << cookie.toRawForm();