/*
* Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
*
* Privacy Browser PC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
// Application headers.
+#include "GlobalVariables.h"
#include "PrivacyWebEngineView.h"
+#include "PrivacyWebEnginePage.h"
#include "Settings.h"
#include "ui_HttpAuthenticationDialog.h"
#include "databases/CookiesDatabase.h"
#include "databases/DomainsDatabase.h"
#include "dialogs/HttpAuthenticationDialog.h"
+#include "helpers/FilterListHelper.h"
#include "interceptors/UrlRequestInterceptor.h"
#include "windows/BrowserWindow.h"
webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
// Create a WebEngine page.
- QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
+ PrivacyWebEnginePage *privacyWebEnginePagePointer = new PrivacyWebEnginePage(webEngineProfilePointer);
// Set the WebEngine page.
- setPage(webEnginePagePointer);
+ setPage(privacyWebEnginePagePointer);
// Get handles for the various aspects of the WebEngine.
- webEngineSettingsPointer = webEnginePagePointer->settings();
+ webEngineSettingsPointer = privacyWebEnginePagePointer->settings();
// Instantiate the URL request interceptor.
UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor(this);
// Set the URL request interceptor.
webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
- // Reapply the domain settings when the host changes.
+ // Connect the URL request interceptor signals.
connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(const QString&)), this, SLOT(applyDomainSettingsWithoutReloading(const QString&)));
-
- // Display HTTP Ping blocked dialogs.
+ connect(urlRequestInterceptorPointer, SIGNAL(newMainFrameResource()), this, SLOT(clearRequestsList()));
connect(urlRequestInterceptorPointer, SIGNAL(displayHttpPingDialog(const QString&)), this, SLOT(displayHttpPingDialog(const QString&)));
+ connect(urlRequestInterceptorPointer, SIGNAL(requestProcessed(RequestStruct*)), this, SLOT(storeRequest(RequestStruct*)));
// Handle HTTP authentication requests.
- connect(webEnginePagePointer, SIGNAL(authenticationRequired(const QUrl&, QAuthenticator*)), this, SLOT(handleAuthenticationRequest(const QUrl&, QAuthenticator*)));
+ connect(privacyWebEnginePagePointer, SIGNAL(authenticationRequired(const QUrl&, QAuthenticator*)), this, SLOT(handleAuthenticationRequest(const QUrl&, QAuthenticator*)));
+
+ // Store the link URL whenever a link is hovered.
+ connect(privacyWebEnginePagePointer, SIGNAL(linkHovered(const QString)), this, SLOT(saveHoveredLink(const QString)));
}
void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const
CookiesDatabase::updateCookie(cookie);
// Update the cookies action.
- emit updateCookiesAction(cookieListPointer->size());
+ emit numberOfCookiesChanged(cookieListPointer->size());
}
void PrivacyWebEngineView::applyDomainSettingsWithoutReloading(const QString &hostname)
// 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;
- }
+ case (DomainsDatabase::SYSTEM_DEFAULT): webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled()); break;
+ case (DomainsDatabase::ENABLED): webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true); break;
+ 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;
- }
+ case (DomainsDatabase::SYSTEM_DEFAULT): localStorageEnabled = Settings::localStorageEnabled(); break;
+ case (DomainsDatabase::ENABLED): localStorageEnabled = true; break;
+ case (DomainsDatabase::DISABLED): localStorageEnabled = false; break;
}
- // Set the DOM storage status.
+ // Set the DOM storage status. QWebEngineSettings confusingly calls this local storage.
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());
+ case (DomainsDatabase::SYSTEM_DEFAULT): webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled()); break;
+ case (DomainsDatabase::ENABLED): webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); break;
+ case (DomainsDatabase::DISABLED): webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); break;
+ }
- break;
- }
+ // Set the user agent.
+ webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainQuery.value(DomainsDatabase::USER_AGENT).toString()));
- // Enable DOM storage. QWebEngineSettings confusingly calls this local storage.
- case (DomainsDatabase::ENABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
+ // Set the UltraPrivacy status.
+ switch (domainQuery.value(DomainsDatabase::ULTRAPRIVACY).toInt())
+ {
+ case (DomainsDatabase::SYSTEM_DEFAULT): ultraPrivacyEnabled = Settings::ultraPrivacyEnabled(); break;
+ case (DomainsDatabase::ENABLED): ultraPrivacyEnabled = true; break;
+ case (DomainsDatabase::DISABLED): ultraPrivacyEnabled = false; break;
+ }
- break;
- }
+ // Set the UltraList status.
+ switch (domainQuery.value(DomainsDatabase::ULTRALIST).toInt())
+ {
+ case (DomainsDatabase::SYSTEM_DEFAULT): ultraListEnabled = Settings::ultraListEnabled(); break;
+ case (DomainsDatabase::ENABLED): ultraListEnabled = true; break;
+ case (DomainsDatabase::DISABLED): ultraListEnabled = false; break;
+ }
- // Disable DOM storage. QWebEngineSettings confusingly calls this local storage.
- case (DomainsDatabase::DISABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
+ // Set the EasyPrivacy status.
+ switch (domainQuery.value(DomainsDatabase::EASYPRIVACY).toInt())
+ {
+ case (DomainsDatabase::SYSTEM_DEFAULT): easyPrivacyEnabled = Settings::easyPrivacyEnabled(); break;
+ case (DomainsDatabase::ENABLED): easyPrivacyEnabled = true; break;
+ case (DomainsDatabase::DISABLED): easyPrivacyEnabled = false; break;
+ }
- break;
- }
+ // Set the EasyList status.
+ switch (domainQuery.value(DomainsDatabase::EASYLIST).toInt())
+ {
+ case (DomainsDatabase::SYSTEM_DEFAULT): easyListEnabled = Settings::easyListEnabled(); break;
+ case (DomainsDatabase::ENABLED): easyListEnabled = true; break;
+ case (DomainsDatabase::DISABLED): easyListEnabled = false; break;
}
- // Set the user agent.
- webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainQuery.value(DomainsDatabase::USER_AGENT).toString()));
+ // Set the Fanboy's Annoyance List status.
+ switch (domainQuery.value(DomainsDatabase::FANBOYS_ANNOYANCE_LIST).toInt())
+ {
+ case (DomainsDatabase::SYSTEM_DEFAULT): fanboysAnnoyanceListEnabled = Settings::fanboysAnnoyanceListEnabled(); break;
+ case (DomainsDatabase::ENABLED): fanboysAnnoyanceListEnabled = true; break;
+ case (DomainsDatabase::DISABLED): fanboysAnnoyanceListEnabled = false; break;
+ }
// Check if a custom zoom factor is set.
if (domainQuery.value(DomainsDatabase::ZOOM_FACTOR).toInt())
// Set the user agent.
webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
+ // Set the status for each filter list.
+ ultraPrivacyEnabled = Settings::ultraPrivacyEnabled();
+ ultraListEnabled = Settings::ultraListEnabled();
+ easyPrivacyEnabled = Settings::easyPrivacyEnabled();
+ easyListEnabled = Settings::easyListEnabled();
+ fanboysAnnoyanceListEnabled = Settings::fanboysAnnoyanceListEnabled();
+
// Store the zoom factor.
defaultZoomFactor = Settings::zoomFactor();
}
if (reloadWebsite)
reload();
+ // Reset the HTTP authentication dialog counter.
+ httpAuthenticationDialogsDisplayed = 0;
+
// Update the UI.
emit updateUi(this);
}
+void PrivacyWebEngineView::clearRequestsList()
+{
+ // Reset the number of blocked requests.
+ blockedRequestsVector[ULTRAPRIVACY] = 0;
+ blockedRequestsVector[ULTRALIST] = 0;
+ blockedRequestsVector[EASYPRIVACY] = 0;
+ blockedRequestsVector[EASYLIST] = 0;
+ blockedRequestsVector[FANBOYS_ANNOYANCE_LIST] = 0;
+ blockedRequestsVector[TOTAL] = 0;
+
+ // Clear the requests list.
+ requestsListPointer->clear();
+
+ // Update the blocked requests action.
+ emit(requestBlocked(blockedRequestsVector));
+}
+
void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) {
// Get a handle for the
QWebEnginePage *webEnginePagePointer = page();
// 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.
+ // Move the open in new tab action above the back action.
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.
+ // Add the open link in background tab action above the back 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.
+ // Move the open in new window action above the back action.
contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow));
- // Add a separator below the open in new window action.
+ // Add a separator above the back action.
contextMenu->insertSeparator(webEnginePagePointer->action(QWebEnginePage::Back));
+
+ if (globalFirefoxInstalled || globalChromiumInstalled)
+ {
+ // Add the open with Firefox action if Firefox is installed.
+ if (globalFirefoxInstalled)
+ {
+ // Create an open with Firefox action.
+ QAction *openWithFirefoxActionPointer = new QAction(QIcon::fromTheme(QLatin1String("firefox-esr")), i18nc("Open with Firefox context menu action", "Open with Firefox"), contextMenu);
+
+ // Add the open with Firefox action above the back action.
+ contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), openWithFirefoxActionPointer);
+
+ // Connect the action.
+ connect(openWithFirefoxActionPointer, SIGNAL(triggered()), this, SLOT(openWithFirefox()));
+ }
+
+ // Add the open with Chromium action if Chromium is installed.
+ if (globalChromiumInstalled)
+ {
+ // Create an open with Chromium action.
+ QAction *openWithChromiumActionPointer = new QAction(QIcon::fromTheme(QLatin1String("chromium")), i18nc("Open with Chromium context menu action", "Open with Chromium"), contextMenu);
+
+ // Add the open with Chromium action above the back action.
+ contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::Back), openWithChromiumActionPointer);
+
+ // Connect the action.
+ connect(openWithChromiumActionPointer, SIGNAL(triggered()), this, SLOT(openWithChromium()));
+ }
+
+
+ // Add a separator above the back action.
+ contextMenu->insertSeparator(webEnginePagePointer->action(QWebEnginePage::Back));
+ }
}
// Display the menu using the location in the context menu event.
void PrivacyWebEngineView::handleAuthenticationRequest(const QUrl &requestUrl, QAuthenticator *authenticatorPointer)
{
- // Instantiate an HTTP authentication dialog.
- HttpAuthenticationDialog *httpAuthenticationDialogPointer = new HttpAuthenticationDialog(parentWidget(), requestUrl, authenticatorPointer);
+ // Only display the HTTP authentication dialog if it hasn't already been displayed three times for this URL.
+ if (httpAuthenticationDialogsDisplayed < 3) {
+ // Increment the HTTP authentication dialog display counter.
+ ++httpAuthenticationDialogsDisplayed;
+
+ // Instantiate an HTTP authentication dialog.
+ HttpAuthenticationDialog *httpAuthenticationDialogPointer = new HttpAuthenticationDialog(parentWidget(), requestUrl, authenticatorPointer);
+
+ // Display the dialog. This must be `exec()` instead of `show()` so that the website doesn't proceed before populating the authentication pointer.
+ httpAuthenticationDialogPointer->exec();
+ }
+}
+
+void PrivacyWebEngineView::openWithChromium() const
+{
+ // Open the current URL in Chromium
+ QProcess::startDetached("chromium", QStringList(hoveredLinkString));
+}
- // Display the dialog. This must be `exec()` instead of `show()` so that the website doesn't proceed before populating the authentication pointer.
- httpAuthenticationDialogPointer->exec();
+void PrivacyWebEngineView::openWithFirefox() const
+{
+ // Open the current URL in Firefox.
+ QProcess::startDetached("firefox-esr", QStringList(hoveredLinkString));
}
void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
cookieListPointer->remove(cookie);
// Update the cookies action.
- emit updateCookiesAction(cookieListPointer->size());
+ emit numberOfCookiesChanged(cookieListPointer->size());
+}
+
+void PrivacyWebEngineView::saveHoveredLink(const QString &hoveredLink)
+{
+ // Save the hovered link.
+ hoveredLinkString = hoveredLink;
+}
+
+void PrivacyWebEngineView::storeRequest(RequestStruct *requestStructPointer)
+{
+ // Store the request struct in the list.
+ requestsListPointer->append(requestStructPointer);
+
+ // Track blocked requests.
+ if (requestStructPointer->dispositionInt == FilterListHelper::BLOCKED)
+ {
+ // Update the individual filter list block counters.
+ if (requestStructPointer->filterListTitle == QLatin1String("UltraPrivacy"))
+ ++blockedRequestsVector[ULTRAPRIVACY];
+ else if (requestStructPointer->filterListTitle == QLatin1String("UltraList"))
+ ++blockedRequestsVector[ULTRALIST];
+ else if (requestStructPointer->filterListTitle == QLatin1String("EasyPrivacy"))
+ ++blockedRequestsVector[EASYPRIVACY];
+ else if (requestStructPointer->filterListTitle == QLatin1String("EasyList"))
+ ++blockedRequestsVector[EASYLIST];
+ else if (requestStructPointer->filterListTitle == QLatin1String("Fanboy's Annoyance List"))
+ ++blockedRequestsVector[FANBOYS_ANNOYANCE_LIST];
+
+ // Update the total requests blocked counter.
+ ++blockedRequestsVector[TOTAL];
+
+ // Update the blocked requests action.
+ emit(requestBlocked(blockedRequestsVector));
+ }
}