X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=src%2Fwidgets%2FPrivacyWebEngineView.cpp;h=10a3a47fcf3f7124a194ce4c62f31b273c5eeaac;hb=HEAD;hp=d7b3f8c1de62a7be5050dc274503d29a690781a2;hpb=15219459baed09d03d17a12c72302595c135fd53;p=PrivacyBrowserPC.git diff --git a/src/widgets/PrivacyWebEngineView.cpp b/src/widgets/PrivacyWebEngineView.cpp index d7b3f8c..15ee508 100644 --- a/src/widgets/PrivacyWebEngineView.cpp +++ b/src/widgets/PrivacyWebEngineView.cpp @@ -1,7 +1,7 @@ /* - * Copyright © 2022 Soren Stoutner . + * Copyright 2022-2024 Soren Stoutner . * - * This file is part of Privacy Browser PC . + * This file is part of 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 @@ -19,7 +19,13 @@ // Application headers. #include "PrivacyWebEngineView.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" // Qt toolkit headers. @@ -27,7 +33,35 @@ #include // Construct the class. -PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr) {} +PrivacyWebEngineView::PrivacyWebEngineView(QWidget *parentWidgetPointer) : QWebEngineView(parentWidgetPointer) +{ + // 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(this); + + // Set the URL request interceptor. + webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer); + + // Connect the URL request interceptor signals. + connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(const QString&)), this, SLOT(applyDomainSettingsWithoutReloading(const QString&))); + 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*))); +} void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const { @@ -41,7 +75,170 @@ 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) +{ + // 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(); + + // Reset the HTTP authentication dialog counter. + httpAuthenticationDialogsDisplayed = 0; + + // Update the UI. + emit updateUi(this); +} + +void PrivacyWebEngineView::clearRequestsList() +{ + // Reset the number of blocked requests. + blockedRequests = 0; + + // Clear the requests list. + requestsListPointer->clear(); + + // Update the blocked requests action. + emit(requestBlocked(blockedRequests)); } void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) { @@ -56,7 +253,19 @@ void PrivacyWebEngineView::contextMenuEvent(QContextMenuEvent *contextMenuEvent) // 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))) - contextMenu->insertAction(webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewWindow), webEnginePagePointer->action(QWebEnginePage::OpenLinkInNewBackgroundTab)); + { + // 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()); @@ -66,14 +275,14 @@ QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType // Get a handle for the browser window. BrowserWindow *browserWindowPointer = qobject_cast(window()); - // Create the requsted window type. + // 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. + // Create the new tab and return the privacy WebEngine view pointer. `true` removes the focus from the blank URL line edit. `true` adds the new tab adjacent to the current 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(true); + return browserWindowPointer->tabWidgetPointer->addTab(true, true); } case QWebEnginePage::WebBrowserWindow: @@ -90,19 +299,41 @@ QWebEngineView* PrivacyWebEngineView::createWindow(QWebEnginePage::WebWindowType 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. + // Create the new tab and return the privacy WebEngine view pointer. `false` does not clear the URL line edit. `true` adds the new tab adjacent to the current tab. + // `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); + return browserWindowPointer->tabWidgetPointer->addTab(false, true, true); } default: { - // Return an null pointer for opening a background tab and opening a web dialog. + // 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::handleAuthenticationRequest(const QUrl &requestUrl, QAuthenticator *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::removeCookieFromList(const QNetworkCookie &cookie) const { //qDebug() << "Remove cookie: " << cookie.toRawForm(); @@ -111,5 +342,21 @@ void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) co cookieListPointer->remove(cookie); // Update the cookies action. - emit updateCookiesAction(cookieListPointer->size()); + emit numberOfCookiesChanged(cookieListPointer->size()); +} + +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 blocked requests counter. + ++blockedRequests; + + // Update the blocked requests action. + emit(requestBlocked(blockedRequests)); + } }