]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blobdiff - src/views/BrowserView.cpp
Add a download location setting.
[PrivacyBrowserPC.git] / src / views / BrowserView.cpp
index 2e29ea0caf9fd515690e9205f498cdd621659c20..f17a237d6d33d962db9315eb3a9602504f79bddc 100644 (file)
 
 // Application headers.
 #include "BrowserView.h"
-#include "MouseEventFilter.h"
 #include "Settings.h"
 #include "ui_BrowserView.h"
-#include "helpers/DomainsDatabaseHelper.h"
+#include "databases/CookiesDatabase.h"
+#include "databases/DomainsDatabase.h"
+#include "dialogs/SaveDialog.h"
+#include "filters/MouseEventFilter.h"
 #include "helpers/SearchEngineHelper.h"
 #include "helpers/UserAgentHelper.h"
 #include "interceptors/UrlRequestInterceptor.h"
 #include "windows/BrowserWindow.h"
 
-// Qt framework headers.
+// KDE Framework headers.
+#include <KIO/FileCopyJob>
+#include <KIO/JobUiDelegate>
+
+// Qt toolkit headers.
 #include <QAction>
-#include <QWebEngineProfile>
+#include <QFileDialog>
+#include <QPrintDialog>
+#include <QPrintPreviewDialog>
+#include <QPrinter>
 
 // Initialize the public static variables.
 QString BrowserView::webEngineDefaultUserAgent = QStringLiteral("");
 
+// Construct the class.
 BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
 {
+    // Initialize the variables.
+    privacyWebEngineListPointer = new QList<PrivacyWebEngine*>;
+
     // Instantiate the browser view UI.
     Ui::BrowserView browserViewUi;
 
@@ -50,14 +63,79 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     webEngineProfilePointer = new QWebEngineProfile(QStringLiteral(""));
 
     // Create a WebEngine page.
-    QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
+    webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
 
     // Set the WebEngine page.
     webEngineViewPointer->setPage(webEnginePagePointer);
 
+    // Handle full screen requests.
+    connect(webEnginePagePointer, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest)));
+
     // Get handles for the aspects of the WebEngine.
     webEngineHistoryPointer = webEnginePagePointer->history();
     webEngineSettingsPointer = webEngineViewPointer->settings();
+    webEngineCookieStorePointer = webEngineProfilePointer->cookieStore();
+
+    // Initialize the current privacy web engine pointer.
+    currentPrivacyWebEnginePointer = new PrivacyWebEngine(webEngineViewPointer);
+
+    // Populate the privacy web engine list.
+    privacyWebEngineListPointer->append(currentPrivacyWebEnginePointer);
+
+    // Set the local storage filter.
+    webEngineCookieStorePointer->setCookieFilter([this](const QWebEngineCookieStore::FilterRequest &filterRequest)
+    {
+        //qDebug().noquote().nospace() << "Page URL:  " << filterRequest.firstPartyUrl << ", Local storage URL:  " << filterRequest.origin << ",  Is third-party:  " << filterRequest.thirdParty;
+
+        // Block all third party local storage requests, including the sneaky ones that don't register a first party URL.
+        if (filterRequest.thirdParty || (filterRequest.firstPartyUrl == QStringLiteral("")))
+        {
+            //qDebug() << "Request blocked.";
+
+            // Return false.
+            return false;
+        }
+
+        /*  TODO.  Waiting for a solution to <https://redmine.stoutner.com/issues/857>.
+        // Check each tab to see if this local storage request should be allowed.
+        for (PrivacyWebEngine *privacyWebEnginePointer : *privacyWebEngineListPointer)
+        {
+            //qDebug().noquote().nospace() << "Local storage:  " << privacyWebEnginePointer->localStorageEnabled << ".  WebEngine URL:  " << webEngineViewPointer->url().host() << ".  Request Host:  " << filterRequest.firstPartyUrl.host();
+
+            // Allow this local storage request if it comes from a tab with local storage enabled.
+            if (privacyWebEnginePointer->localStorageEnabled && (webEngineViewPointer->url().host() == filterRequest.firstPartyUrl.host()))
+            {
+                //qDebug() << "Request allowed.";
+
+                // Return true.
+                return true;
+            }
+        }
+        */
+
+        // Allow the request if it is first party and local storage is enabled.
+        if (!filterRequest.thirdParty && currentPrivacyWebEnginePointer->localStorageEnabled)
+        {
+            // Return true.
+            return true;
+        }
+
+        //qDebug() << "Request blocked.";
+
+        // Block any remaining local storage requests.
+        return false;
+    });
+
+    // Process cookie changes.
+    connect(webEngineCookieStorePointer, SIGNAL(cookieAdded(QNetworkCookie)), this, SLOT(cookieAdded(QNetworkCookie)));
+    connect(webEngineCookieStorePointer, SIGNAL(cookieRemoved(QNetworkCookie)), this, SLOT(cookieRemoved(QNetworkCookie)));
+
+    // Get a list of durable cookies.
+    QList<QNetworkCookie*> *durableCookiesListPointer = CookiesDatabase::getCookies();
+
+    // Add the durable cookies to the store.
+    for (QNetworkCookie *cookiePointer : *durableCookiesListPointer)
+        addCookieToStore(*cookiePointer);
 
     // Store a copy of the WebEngine default user agent.
     webEngineDefaultUserAgent = webEngineProfilePointer->httpUserAgent();
@@ -71,11 +149,15 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     connect(webEngineViewPointer, SIGNAL(loadFinished(const bool)), this, SLOT(loadFinished()));
 
     // Instantiate the mouse event filter pointer.
-    MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter(webEngineViewPointer);
+    MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter();
 
     // Install the mouse event filter.
     qApp->installEventFilter(mouseEventFilterPointer);
 
+    // Process mouse forward and back commands.
+    connect(mouseEventFilterPointer, SIGNAL(mouseBack()), this, SLOT(mouseBack()));
+    connect(mouseEventFilterPointer, SIGNAL(mouseForward()), this, SLOT(mouseForward()));
+
     // Listen for hovered link URLs.
     connect(webEnginePagePointer, SIGNAL(linkHovered(const QString)), this, SLOT(pageLinkHovered(const QString)));
 
@@ -85,6 +167,9 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     // Set the URL request interceptor.
     webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
 
+    // Handle file downloads.
+    connect(webEngineProfilePointer, SIGNAL(downloadRequested(QWebEngineDownloadItem *)), this, SLOT(showSaveDialog(QWebEngineDownloadItem *)));
+
     // Reapply the domain settings when the host changes.
     connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(QString)), this, SLOT(applyDomainSettingsWithoutReloading(QString)));
 
@@ -107,13 +192,40 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     webEngineViewPointer->setFocus();
 }
 
+BrowserView::~BrowserView()
+{
+    // Delay the deletion of the WebEngine page to prevent the following error:  `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+    webEnginePagePointer->deleteLater();
+}
+
+// The cookie is copied instead of referenced so that changes made to the cookie do not create a race condition with the display of the cookie in the dialog.
+void BrowserView::addCookieToStore(QNetworkCookie cookie) const
+{
+    // Create a url.
+    QUrl url;
+
+    // Check to see if the domain does not start with a `.` because Qt makes this harder than it should be.  <https://doc.qt.io/qt-5/qwebenginecookiestore.html#setCookie>
+    if (!cookie.domain().startsWith(QStringLiteral(".")))
+    {
+        // Populate the URL.
+        url.setHost(cookie.domain());
+        url.setScheme(QStringLiteral("https"));
+
+        // Clear the domain from the cookie.
+        cookie.setDomain(QStringLiteral(""));
+    }
+
+    // Add the cookie to the store.
+    webEngineCookieStorePointer->setCookie(cookie, url);
+}
+
 void BrowserView::applyApplicationSettings()
 {
     // Set the search engine URL.
     searchEngineUrl = SearchEngineHelper::getSearchUrl(Settings::searchEngine());
 
     // Emit the update search engine actions signal.
-    emit updateSearchEngineActions(Settings::searchEngine());
+    emit updateSearchEngineActions(Settings::searchEngine(), true);
 }
 
 // This exists as a separate function from `applyDomainSettings()` so it can be listed as a slot and function without the need for a boolean argument.
@@ -136,7 +248,7 @@ void BrowserView::applyDomainSettingsWithoutReloading(const QString &hostname)
 void BrowserView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
 {
     // Get the record for the hostname.
-    QSqlQuery domainQuery = DomainsDatabaseHelper::getDomainQuery(hostname);
+    QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
 
     // Check if the hostname has domain settings.
     if (domainQuery.isValid())  // The hostname has domain settings.
@@ -145,55 +257,83 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload
         QSqlRecord domainRecord = domainQuery.record();
 
         // Set the JavaScript status.
-        switch (domainRecord.field(DomainsDatabaseHelper::JAVASCRIPT).value().toInt())
+        switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
         {
-            case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+            // Set the default JavaScript status.
+            case (DomainsDatabase::SYSTEM_DEFAULT):
             {
-                // Set the default JavaScript status.
-                webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScript());
+                webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
 
                 break;
             }
 
-            case (DomainsDatabaseHelper::DISABLED):
+            // Disable JavaScript.
+            case (DomainsDatabase::DISABLED):
             {
-                // Disable JavaScript.
                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
 
                 break;
             }
 
-            case (DomainsDatabaseHelper::ENABLED):
+            // Enable JavaScript.
+            case (DomainsDatabase::ENABLED):
             {
-                // Enable JavaScript.
                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
 
                 break;
             }
         }
 
-        // Set local storage.
-        switch (domainRecord.field(DomainsDatabaseHelper::LOCAL_STORAGE).value().toInt())
+        // Set the local storage status.
+        switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
+        {
+            // Set the default local storage status.
+            case (DomainsDatabase::SYSTEM_DEFAULT):
+            {
+                currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled();
+
+                break;
+            }
+
+            // Disable local storage.
+            case (DomainsDatabase::DISABLED):
+            {
+                currentPrivacyWebEnginePointer->localStorageEnabled = false;
+
+                break;
+            }
+
+            // Enable local storage.
+            case (DomainsDatabase::ENABLED):
+            {
+                currentPrivacyWebEnginePointer->localStorageEnabled = true;
+
+                break;
+            }
+        }
+
+        // Set the DOM storage status.
+        switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
         {
-            case (DomainsDatabaseHelper::SYSTEM_DEFAULT):
+            // Set the default DOM storage status.
+            case (DomainsDatabase::SYSTEM_DEFAULT):
             {
-                // Set the default local storage status.
-                webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::localStorage());
+                webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
 
                 break;
             }
 
-            case (DomainsDatabaseHelper::DISABLED):
+            // Disable DOM storage.
+            case (DomainsDatabase::DISABLED):
             {
-                // Disable local storage.
                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
 
                 break;
             }
 
-            case (DomainsDatabaseHelper::ENABLED):
+            // Enable DOM storage.
+            case (DomainsDatabase::ENABLED):
             {
-                // Enable local storage.
                 webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
 
                 break;
@@ -201,13 +341,13 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload
         }
 
         // Set the user agent.
-        webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabaseHelper::USER_AGENT).value().toString()));
+        webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
 
         // Check if a custom zoom factor is set.
-        if (domainRecord.field(DomainsDatabaseHelper::ZOOM_FACTOR).value().toInt())
+        if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
         {
             // Store the current zoom factor.
-            currentZoomFactor = domainRecord.field(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR).value().toDouble();
+            currentZoomFactor = domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble();
         }
         else
         {
@@ -219,15 +359,18 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload
         webEngineViewPointer->setZoomFactor(currentZoomFactor);
 
         // Apply the domain settings palette to the URL line edit.
-        emit updateDomainSettingsIndicator(true, domainRecord.field(DomainsDatabaseHelper::DOMAIN_NAME).value().toString());
+        emit updateDomainSettingsIndicator(true, domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString());
     }
     else  // The hostname does not have domain settings.
     {
         // Set the JavaScript status.
-        webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScript());
+        webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
+
+        // Set the local storage status.
+        currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled();
 
-        // Set local storage.
-        webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::localStorage());
+        // Set DOM storage.
+        webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
 
         // Set the user agent.
         webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
@@ -244,15 +387,14 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload
 
     // Emit the update actions signals.
     emit updateJavaScriptAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
-    emit updateLocalStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
-    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent());
+    emit updateLocalStorageAction(currentPrivacyWebEnginePointer->localStorageEnabled);
+    emit updateDomStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), true);
     emit updateZoomFactorAction(webEngineViewPointer->zoomFactor());
 
     // Reload the website if requested.
     if (reloadWebsite)
-    {
         webEngineViewPointer->reload();
-    }
 }
 
 void BrowserView::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
@@ -265,6 +407,9 @@ void BrowserView::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
 
     // Store the search engine string.
     searchEngineUrl = SearchEngineHelper::getSearchUrl(searchEngineName);
+
+    // Update the search engine actionas.
+    emit updateSearchEngineActions(searchEngineName, false);
 }
 
 void BrowserView::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
@@ -278,6 +423,9 @@ void BrowserView::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
     // Apply the user agent.
     webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromTranslatedName(userAgentName));
 
+    // Update the user agent actions.
+    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), false);
+
     // Reload the website.
     webEngineViewPointer->reload();
 }
@@ -298,12 +446,45 @@ void BrowserView::back() const
     webEngineViewPointer->back();
 }
 
+void BrowserView::cookieAdded(const QNetworkCookie &cookie) const
+{
+    // Add the cookie to the cookie list.
+    emit addCookie(cookie);
+}
+
+void BrowserView::cookieRemoved(const QNetworkCookie &cookie) const
+{
+    // Remove the cookie from the cookie list.
+    emit removeCookie(cookie);
+}
+
+void BrowserView::deleteAllCookies() const
+{
+    // Delete all the cookies.
+    webEngineCookieStorePointer->deleteAllCookies();
+}
+
+void BrowserView::deleteCookieFromStore(const QNetworkCookie &cookie) const
+{
+    // Delete the cookie.
+    webEngineCookieStorePointer->deleteCookie(cookie);
+}
+
 void BrowserView::forward() const
 {
     // Go forward.
     webEngineViewPointer->forward();
 }
 
+void BrowserView::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const
+{
+    // Make it so.
+    emit fullScreenRequested(fullScreenRequest.toggleOn());
+
+    // Accept the request.
+    fullScreenRequest.accept();
+}
+
 void BrowserView::home() const
 {
     // Load the homepage.
@@ -376,37 +557,184 @@ void BrowserView::loadUrlFromLineEdit(QString url) const
     }
 }
 
+void BrowserView::mouseBack() const
+{
+    // Go back if possible.
+    if (webEngineViewPointer->isActiveWindow() && webEngineHistoryPointer->canGoBack())
+    {
+        // Clear the URL line edit focus.
+        emit clearUrlLineEditFocus();
+
+        // Go back.
+        webEngineViewPointer->back();
+    }
+}
+
+void BrowserView::mouseForward() const
+{
+    // Go forward if possible.
+    if (webEngineViewPointer->isActiveWindow() && webEngineHistoryPointer->canGoForward())
+    {
+        // Clear the URL line edit focus.
+        emit clearUrlLineEditFocus();
+
+        // Go forward.
+        webEngineViewPointer->forward();
+    }
+}
+
 void BrowserView::pageLinkHovered(const QString &linkUrl) const
 {
     // Emit a signal so that the browser window can update the status bar.
     emit linkHovered(linkUrl);
 }
 
+void BrowserView::print() const
+{
+    // Create a printer.
+    QPrinter printer;
+
+    // Set the resolution to be 300 dpi.
+    printer.setResolution(300);
+
+    // Create a printer dialog.
+    QPrintDialog printDialog(&printer, webEngineViewPointer);
+
+    // Display the dialog and print the page if instructed.
+    if (printDialog.exec() == QDialog::Accepted)
+        printWebpage(&printer);
+}
+
+void BrowserView::printPreview() const
+{
+    // Create a printer.
+    QPrinter printer;
+
+    // Set the resolution to be 300 dpi.
+    printer.setResolution(300);
+
+    // Create a print preview dialog.
+    QPrintPreviewDialog printPreviewDialog(&printer, webEngineViewPointer);
+
+    // Generate the print preview.
+    connect(&printPreviewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(printWebpage(QPrinter *)));
+
+    // Display the dialog.
+    printPreviewDialog.exec();
+}
+
+void BrowserView::printWebpage(QPrinter *printerPointer) const
+{
+    // Create an event loop.  For some reason, the print preview doesn't produce any output unless it is run inside an event loop.
+    QEventLoop eventLoop;
+
+    // Print the webpage, converting the callback above into a `QWebEngineCallback<bool>`.
+    // Printing requires that the printer be a pointer, not a reference, or it will crash with much cursing.
+    webEnginePagePointer->print(printerPointer, [&eventLoop](bool printSuccess)
+    {
+        // Instruct the compiler to ignore the unused parameter.
+        (void) printSuccess;
+
+        // Quit the loop.
+        eventLoop.quit();
+    });
+
+    // Execute the loop.
+    eventLoop.exec();
+}
+
 void BrowserView::refresh() const
 {
     // Reload the website.
     webEngineViewPointer->reload();
 }
 
+void BrowserView::showSaveDialog(QWebEngineDownloadItem *downloadItemPointer) const
+{
+    // Instantiate the save dialog.
+    SaveDialog *saveDialogPointer = new SaveDialog(downloadItemPointer);
+
+    // Connect the save button.
+    connect(saveDialogPointer, SIGNAL(showSaveFilePickerDialog(QUrl &, QString &)), this, SLOT(showSaveFilePickerDialog(QUrl &, QString &)));
+
+    // Show the dialog.
+    saveDialogPointer->show();
+}
+
+void BrowserView::showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName)
+{
+    // Get the download location.
+    QString downloadDirectory = Settings::downloadLocation();
+
+    // Resolve the system download directory if specified.
+    if (downloadDirectory == QStringLiteral("System Download Directory"))
+        downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+
+    // Create a save file dialog.
+    QFileDialog *saveFileDialogPointer = new QFileDialog(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory);
+
+    // Tell the dialog to use a save button.
+    saveFileDialogPointer->setAcceptMode(QFileDialog::AcceptSave);
+
+    // Populate the file name from the download item pointer.
+    saveFileDialogPointer->selectFile(suggestedFileName);
+
+    // Prevent interaction with the parent window while the dialog is open.
+    saveFileDialogPointer->setWindowModality(Qt::WindowModal);
+
+    // Process the saving of the file.  The save file dialog pointer must be captured directly instead of by reference or nasty crashes occur.
+    auto saveFile = [saveFileDialogPointer, &downloadUrl] () {
+        // Get the save location.  The dialog box should only allow the selecting of one file location.
+        QUrl saveLocation = saveFileDialogPointer->selectedUrls().value(0);
+
+        // Create a file copy job.  `-1` creates the file with default permissions.
+        KIO::FileCopyJob *fileCopyJobPointer = KIO::file_copy(downloadUrl, saveLocation, -1, KIO::Overwrite);
+
+        // Set the download job to display any error messages.
+        fileCopyJobPointer->uiDelegate()->setAutoErrorHandlingEnabled(true);
+
+        // Start the download.
+        fileCopyJobPointer->start();
+    };
+
+    // Handle clicks on the save button.
+    connect(saveFileDialogPointer, &QDialog::accepted, this, saveFile);
+
+    // Show the dialog.
+    saveFileDialogPointer->show();
+}
+
+void BrowserView::toggleDomStorage() const
+{
+    // Toggle DOM storage.
+    webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+
+    // Update the DOM storage action.
+    emit updateDomStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+
+    // Reload the website.
+    webEngineViewPointer->reload();
+}
+
 void BrowserView::toggleJavaScript() const
 {
     // Toggle JavaScript.
     webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
 
-    // Update the JavaScript icon.
+    // Update the JavaScript action.
     emit updateJavaScriptAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
 
     // Reload the website.
     webEngineViewPointer->reload();
 }
 
-void BrowserView::toggleLocalStorage() const
+void BrowserView::toggleLocalStorage()
 {
-    // Toggle local storage.
-    webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+    // Toggle local storeage.
+    currentPrivacyWebEnginePointer->localStorageEnabled = !currentPrivacyWebEnginePointer->localStorageEnabled;
 
-    // Update the local storage icon.
-    emit updateLocalStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+    // Update the local storage action.
+    emit updateLocalStorageAction(currentPrivacyWebEnginePointer->localStorageEnabled);
 
     // Reload the website.
     webEngineViewPointer->reload();