From cd1c3d0483b9026736fdcb151d90dda872d8a400 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Thu, 26 May 2022 16:33:20 -0700 Subject: [PATCH] Add durable cookie support. --- src/CMakeLists.txt | 1 + src/databases/CMakeLists.txt | 23 + src/databases/CookiesDatabase.cpp | 377 +++++++++++++++ src/databases/CookiesDatabase.h | 60 +++ .../DomainsDatabase.cpp} | 58 +-- .../DomainsDatabase.h} | 8 +- src/dialogs/AddOrEditCookieDialog.cpp | 63 ++- src/dialogs/AddOrEditCookieDialog.h | 8 +- src/dialogs/CookiesDialog.cpp | 438 +++++++++--------- src/dialogs/CookiesDialog.h | 9 +- src/dialogs/DomainSettingsDialog.cpp | 80 ++-- src/helpers/CMakeLists.txt | 1 - src/main.cpp | 8 +- src/uis/AddOrEditCookieDialog.ui | 58 ++- src/views/BrowserView.cpp | 47 +- src/views/BrowserView.h | 2 +- src/windows/BrowserWindow.cpp | 5 + 17 files changed, 905 insertions(+), 341 deletions(-) create mode 100644 src/databases/CMakeLists.txt create mode 100644 src/databases/CookiesDatabase.cpp create mode 100644 src/databases/CookiesDatabase.h rename src/{helpers/DomainsDatabaseHelper.cpp => databases/DomainsDatabase.cpp} (81%) rename src/{helpers/DomainsDatabaseHelper.h => databases/DomainsDatabase.h} (93%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb70231..fd274ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,7 @@ target_link_libraries(privacy-browser ) # Add the subdirectories. +add_subdirectory(databases) add_subdirectory(dialogs) add_subdirectory(filters) add_subdirectory(helpers) diff --git a/src/databases/CMakeLists.txt b/src/databases/CMakeLists.txt new file mode 100644 index 0000000..0abb936 --- /dev/null +++ b/src/databases/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright © 2022 Soren Stoutner . +# +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Privacy Browser PC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Privacy Browser PC. If not, see . + + +# List the sources to include in the executable. +target_sources(privacy-browser PRIVATE + CookiesDatabase.cpp + DomainsDatabase.cpp +) diff --git a/src/databases/CookiesDatabase.cpp b/src/databases/CookiesDatabase.cpp new file mode 100644 index 0000000..adc4f1b --- /dev/null +++ b/src/databases/CookiesDatabase.cpp @@ -0,0 +1,377 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +// Application headers. +#include "CookiesDatabase.h" + +// Define the private static schema constants. +const int CookiesDatabase::SCHEMA_VERSION = 0; + +// Define the public static database constants. +const QString CookiesDatabase::CONNECTION_NAME = "cookies_database"; +const QString CookiesDatabase::COOKIES_TABLE = "cookies"; + +// Define the public static database field names. +const QString CookiesDatabase::_ID = "_id"; +const QString CookiesDatabase::DOMAIN = "domain"; +const QString CookiesDatabase::NAME = "name"; +const QString CookiesDatabase::PATH = "path"; +const QString CookiesDatabase::EXPIRATION_DATE = "expiration_date"; +const QString CookiesDatabase::HTTP_ONLY = "http_only"; +const QString CookiesDatabase::SECURE = "secure"; +const QString CookiesDatabase::VALUE = "value"; + +// Construct the class. +CookiesDatabase::CookiesDatabase() {} + +void CookiesDatabase::addDatabase() +{ + // Add the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME); + + // Set the database name. + cookiesDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/cookies.db"); + + // Open the database. + if (cookiesDatabase.open()) // Opening the database succeeded. + { + // Check to see if the cookies table already exists. + if (cookiesDatabase.tables().contains(COOKIES_TABLE)) // The cookies table exists. + { + // Query the database schema version. + QSqlQuery schemaVersionQuery = cookiesDatabase.exec(QStringLiteral("PRAGMA user_version")); + + // Move to the first record. + schemaVersionQuery.first(); + + // Get the current schema versin. + int currentSchemaVersion = schemaVersionQuery.value(0).toInt(); + + // Check to see if the schema has been updated. + if (currentSchemaVersion < SCHEMA_VERSION) + { + // Run the schema update code. + switch (currentSchemaVersion) + { + // Upgrade code here. + } + + // Update the schema version. + cookiesDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION)); + } + } + else // The cookies table does not exist. + { + // Instantiate a create table query. + QSqlQuery createTableQuery(cookiesDatabase); + + // Prepare the create table query. + createTableQuery.prepare("CREATE TABLE " + COOKIES_TABLE + "(" + + _ID + " INTEGER PRIMARY KEY, " + + DOMAIN + " TEXT NOT NULL, " + + NAME + " TEXT NOT NULL, " + + PATH + " TEXT NOT NULL, " + + EXPIRATION_DATE + " TEXT, " + + HTTP_ONLY + " INTEGER NOT NULL DEFAULT 0, " + + SECURE + " INTEGER NOT NULL DEFAULT 0, " + + VALUE + " TEXT NOT NULL)" + ); + + // Execute the query. + if (!createTableQuery.exec()) + { + // Log any errors. + qDebug().noquote().nospace() << "Error creating table: " << cookiesDatabase.lastError(); + } + + // Set the schema version. + cookiesDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION)); + } + } + else // Opening the database failed. + { + // Write the last database error message to the debug output. + qDebug().noquote().nospace() << "Error opening database: " << cookiesDatabase.lastError(); + } +} + +void CookiesDatabase::addCookie(const QNetworkCookie &cookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Check to see if the cookie already exists in the database. + if (isDurable(cookie)) // The cookie already exists. + { + // Update the existing cookie. + updateCookie(cookie); + } + else // The cookie doesn't already exist. + { + // Instantiate an add cookie query. + QSqlQuery addCookieQuery(cookiesDatabase); + + // Prepare the add cookie query. + addCookieQuery.prepare("INSERT INTO " + COOKIES_TABLE + " (" + DOMAIN + ", " + NAME + ", " + PATH + ", " + EXPIRATION_DATE + ", " + HTTP_ONLY + ", " + SECURE + ", " + VALUE + ") " + "VALUES (:domain, :name, :path, :expiration_date, :http_only, :secure, :value)" + ); + + // Bind the values. + addCookieQuery.bindValue(":domain", cookie.domain()); + addCookieQuery.bindValue(":name", QString(cookie.name())); + addCookieQuery.bindValue(":path", cookie.path()); + addCookieQuery.bindValue(":expiration_date", cookie.expirationDate()); + addCookieQuery.bindValue(":http_only", cookie.isHttpOnly()); + addCookieQuery.bindValue(":secure", cookie.isSecure()); + addCookieQuery.bindValue(":value", QString(cookie.value())); + + // Execute the query. + addCookieQuery.exec(); + } +} + +void CookiesDatabase::deleteAllCookies() +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate a delete all cookies query. + QSqlQuery deleteAllCookiesQuery(cookiesDatabase); + + // Prepare the delete all cookies query. + deleteAllCookiesQuery.prepare("DELETE FROM " + COOKIES_TABLE); + + // Execute the query. + deleteAllCookiesQuery.exec(); +} + +void CookiesDatabase::deleteCookie(const QNetworkCookie &cookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate a delete cookie query. + QSqlQuery deleteCookieQuery(cookiesDatabase); + + // Prepare the delete cookie query. + deleteCookieQuery.prepare("DELETE FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path"); + + // Bind the values. + deleteCookieQuery.bindValue(":domain", cookie.domain()); + deleteCookieQuery.bindValue(":name", QString(cookie.name())); + deleteCookieQuery.bindValue(":path", cookie.path()); + + // Execute the query. + deleteCookieQuery.exec(); +} + +QList* CookiesDatabase::getCookies() +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate a cookies query. + QSqlQuery cookiesQuery(cookiesDatabase); + + // Set the query to be forward only. + cookiesQuery.setForwardOnly(true); + + // Prepare the cookies query. + cookiesQuery.prepare("SELECT * FROM " + COOKIES_TABLE); + + // Execute the query. + cookiesQuery.exec(); + + // Create a cookie list. + QList *cookieListPointer = new QList; + + // Populate the cookie list. + while (cookiesQuery.next()) + { + // Create a cookie. + QNetworkCookie *cookiePointer = new QNetworkCookie(); + + // Populate the cookie. + cookiePointer->setDomain(cookiesQuery.value(DOMAIN).toString()); + cookiePointer->setName(cookiesQuery.value(NAME).toString().toUtf8()); + cookiePointer->setPath(cookiesQuery.value(PATH).toString()); + cookiePointer->setExpirationDate(QDateTime::fromString(cookiesQuery.value(EXPIRATION_DATE).toString(), Qt::ISODate)); + cookiePointer->setHttpOnly(cookiesQuery.value(HTTP_ONLY).toBool()); + cookiePointer->setSecure(cookiesQuery.value(SECURE).toBool()); + cookiePointer->setValue(cookiesQuery.value(VALUE).toString().toUtf8()); + + // Add the cookie to the list. + cookieListPointer->append(cookiePointer); + } + + // Return the cookie list. + return cookieListPointer; +} + +bool CookiesDatabase::isDurable(const QNetworkCookie &cookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate an is durable query. + QSqlQuery isDurableQuery(cookiesDatabase); + + // Set the query to be forward only. + isDurableQuery.setForwardOnly(true); + + // Prepare the is durable query. + isDurableQuery.prepare("SELECT " + _ID + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path"); + + // Bind the values. + isDurableQuery.bindValue(":domain", cookie.domain()); + isDurableQuery.bindValue(":name", QString(cookie.name())); + isDurableQuery.bindValue(":path", cookie.path()); + + // Execute the query. + isDurableQuery.exec(); + + // Move to the first entry. + isDurableQuery.first(); + + // Return the status of the cookie in the database. + return (isDurableQuery.isValid()); +} + +bool CookiesDatabase::isUpdate(const QNetworkCookie &cookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Instantiate an is update query. + QSqlQuery isUpdateQuery(cookiesDatabase); + + // Prepare the is update query. + isUpdateQuery.prepare("SELECT " + EXPIRATION_DATE + " , " + HTTP_ONLY + " , " + SECURE + " , " + VALUE + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + + NAME + " = :name AND " + PATH + " = :path"); + + // Bind the values. + isUpdateQuery.bindValue(":domain", cookie.domain()); + isUpdateQuery.bindValue(":name", QString(cookie.name())); + isUpdateQuery.bindValue(":path", cookie.path()); + + // Execute the query. + isUpdateQuery.exec(); + + // Move to the first entry. + isUpdateQuery.first(); + + // Check to see if the cookie exists. + if (isUpdateQuery.isValid()) // The cookie exists in the database. + { + // Check to see if the cookie data has changed. + if ((QDateTime::fromString(isUpdateQuery.value(0).toString(), Qt::ISODate) != cookie.expirationDate()) || + (isUpdateQuery.value(1).toBool() != cookie.isHttpOnly()) || + (isUpdateQuery.value(2).toBool() != cookie.isSecure()) || + (isUpdateQuery.value(3).toString().toUtf8() != cookie.value())) // The cookies data has changed. + { + qDebug() << "The durable cookie data has changed."; + + // Return true. + return true; + } + else // The cookie data has not changed. + { + qDebug() << "The durable cookie data is unchanged."; + + // Return false. + return false; + } + } + else // The cookie does not exist in the database. + { + // Return false. + return false; + } +} + +void CookiesDatabase::updateCookie(const QNetworkCookie &cookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Create the update cookie query. + QSqlQuery updateCookieQuery(cookiesDatabase); + + // Prepare the edit cookie query. + updateCookieQuery.prepare("UPDATE " + COOKIES_TABLE + " SET " + EXPIRATION_DATE + " = :expiration_date , " + HTTP_ONLY + " = :http_only , " + SECURE + " = :secure , " + + VALUE + " = :value WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path"); + + // Bind the values. + updateCookieQuery.bindValue(":domain", cookie.domain()); + updateCookieQuery.bindValue(":name", QString(cookie.name())); + updateCookieQuery.bindValue(":path", cookie.path()); + updateCookieQuery.bindValue(":expiration_date", cookie.expirationDate()); + updateCookieQuery.bindValue(":http_only", cookie.isHttpOnly()); + updateCookieQuery.bindValue(":secure", cookie.isSecure()); + updateCookieQuery.bindValue(":value", QString(cookie.value())); + + // Execute the query. + updateCookieQuery.exec(); +} + +void CookiesDatabase::updateCookie(const QNetworkCookie &oldCookie, const QNetworkCookie &newCookie) +{ + // Get a handle for the cookies database. + QSqlDatabase cookiesDatabase = QSqlDatabase::database(CONNECTION_NAME); + + // Create the old cookie query. + QSqlQuery oldCookieQuery(cookiesDatabase); + + // Set the query to be forward only. + oldCookieQuery.setForwardOnly(true); + + // Prepare the old cookie query. + oldCookieQuery.prepare("SELECT " + _ID + " FROM " + COOKIES_TABLE + " WHERE " + DOMAIN + " = :domain AND " + NAME + " = :name AND " + PATH + " = :path"); + + // Bind the values. + oldCookieQuery.bindValue(":domain", oldCookie.domain()); + oldCookieQuery.bindValue(":name", QString(oldCookie.name())); + oldCookieQuery.bindValue(":path", oldCookie.path()); + + // Execute the query. + oldCookieQuery.exec(); + + // Move to the first entry. + oldCookieQuery.first(); + + // Create the update cookie query. + QSqlQuery updateCookieQuery(cookiesDatabase); + + // Prepare the update cookie query. + updateCookieQuery.prepare("UPDATE " + COOKIES_TABLE + " SET " + DOMAIN + " = :domain , " + NAME + " = :name , " + PATH + " = :path , " + EXPIRATION_DATE + " = :expiration_date , " + + HTTP_ONLY + " = :http_only , " + SECURE + " = :secure , " + VALUE + " = :value WHERE " + _ID + " = :id"); + + // Bind the values. + updateCookieQuery.bindValue(":id", oldCookieQuery.value(0).toLongLong()); + updateCookieQuery.bindValue(":domain", newCookie.domain()); + updateCookieQuery.bindValue(":name", QString(newCookie.name())); + updateCookieQuery.bindValue(":path", newCookie.path()); + updateCookieQuery.bindValue(":expiration_date", newCookie.expirationDate()); + updateCookieQuery.bindValue(":http_only", newCookie.isHttpOnly()); + updateCookieQuery.bindValue(":secure", newCookie.isSecure()); + updateCookieQuery.bindValue(":value", QString(newCookie.value())); + + // Execute the query. + updateCookieQuery.exec(); +} diff --git a/src/databases/CookiesDatabase.h b/src/databases/CookiesDatabase.h new file mode 100644 index 0000000..6fcae89 --- /dev/null +++ b/src/databases/CookiesDatabase.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser PC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser PC. If not, see . + */ + +#ifndef COOKIESDATABASE_H +#define COOKIESDATABASE_H + +// Qt framework headers. +#include +#include + +class CookiesDatabase +{ +public: + // The default constructor. + CookiesDatabase(); + + // The public functions. + static void addDatabase(); + static void addCookie(const QNetworkCookie &cookie); + static void deleteAllCookies(); + static void deleteCookie(const QNetworkCookie &cookie); + static QList* getCookies(); + static bool isDurable(const QNetworkCookie &cookie); + static bool isUpdate(const QNetworkCookie &cookie); + static void updateCookie(const QNetworkCookie &cookie); + static void updateCookie(const QNetworkCookie &oldCookie, const QNetworkCookie &newCookie); + + // The public constants. + static const QString _ID; + static const QString CONNECTION_NAME; + static const QString COOKIES_TABLE; + static const QString DOMAIN; + static const QString EXPIRATION_DATE; + static const QString HTTP_ONLY; + static const QString NAME; + static const QString PATH; + static const QString SECURE; + static const QString VALUE; + +private: + // The private static constants. + static const int SCHEMA_VERSION; +}; +#endif diff --git a/src/helpers/DomainsDatabaseHelper.cpp b/src/databases/DomainsDatabase.cpp similarity index 81% rename from src/helpers/DomainsDatabaseHelper.cpp rename to src/databases/DomainsDatabase.cpp index d1f8b22..6dfc1bd 100644 --- a/src/helpers/DomainsDatabaseHelper.cpp +++ b/src/databases/DomainsDatabase.cpp @@ -18,33 +18,33 @@ */ // Application headers. -#include "DomainsDatabaseHelper.h" -#include "UserAgentHelper.h" - -// Define the public static domain constants. -const QString DomainsDatabaseHelper::CONNECTION_NAME = "domains_database"; -const QString DomainsDatabaseHelper::DOMAINS_TABLE = "domains"; +#include "DomainsDatabase.h" +#include "helpers/UserAgentHelper.h" // Define the private static schema constants. -const int DomainsDatabaseHelper::SCHEMA_VERSION = 5; +const int DomainsDatabase::SCHEMA_VERSION = 5; + +// Define the public static database constants. +const QString DomainsDatabase::CONNECTION_NAME = "domains_database"; +const QString DomainsDatabase::DOMAINS_TABLE = "domains"; // Define the public static database field names. -const QString DomainsDatabaseHelper::_ID = "_id"; -const QString DomainsDatabaseHelper::DOMAIN_NAME = "domain_name"; -const QString DomainsDatabaseHelper::JAVASCRIPT = "javascript"; -const QString DomainsDatabaseHelper::LOCAL_STORAGE = "local_storage"; -const QString DomainsDatabaseHelper::DOM_STORAGE = "dom_storage"; -const QString DomainsDatabaseHelper::USER_AGENT = "user_agent"; -const QString DomainsDatabaseHelper::ZOOM_FACTOR = "zoom_factor"; -const QString DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR = "custom_zoom_factor"; +const QString DomainsDatabase::_ID = "_id"; +const QString DomainsDatabase::DOMAIN_NAME = "domain_name"; +const QString DomainsDatabase::JAVASCRIPT = "javascript"; +const QString DomainsDatabase::LOCAL_STORAGE = "local_storage"; +const QString DomainsDatabase::DOM_STORAGE = "dom_storage"; +const QString DomainsDatabase::USER_AGENT = "user_agent"; +const QString DomainsDatabase::ZOOM_FACTOR = "zoom_factor"; +const QString DomainsDatabase::CUSTOM_ZOOM_FACTOR = "custom_zoom_factor"; // Construct the class. -DomainsDatabaseHelper::DomainsDatabaseHelper() {} +DomainsDatabase::DomainsDatabase() {} -void DomainsDatabaseHelper::addDatabase() +void DomainsDatabase::addDatabase() { // Add the domain settings database. - QSqlDatabase domainsDatabase = QSqlDatabase::addDatabase("QSQLITE", CONNECTION_NAME); + QSqlDatabase domainsDatabase = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), CONNECTION_NAME); // Set the database name. domainsDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/domains.db"); @@ -53,21 +53,21 @@ void DomainsDatabaseHelper::addDatabase() if (domainsDatabase.open()) // Opening the database succeeded. { // Check to see if the domains table already exists. - if (domainsDatabase.tables().contains(DOMAINS_TABLE)) + if (domainsDatabase.tables().contains(DOMAINS_TABLE)) // The domains table already exists. { // Query the database schema version. - QSqlQuery getSchemaVersionQuery = domainsDatabase.exec("PRAGMA user_version"); + QSqlQuery schemaVersionQuery = domainsDatabase.exec(QStringLiteral("PRAGMA user_version")); // Move to the first record. - getSchemaVersionQuery.first(); + schemaVersionQuery.first(); // Get the current schema version. - int currentSchemaVersion = getSchemaVersionQuery.value(0).toInt(); + int currentSchemaVersion = schemaVersionQuery.value(0).toInt(); - // Check to see if the schama has been updated. - if (SCHEMA_VERSION > currentSchemaVersion) + // Check to see if the schema has been updated. + if (currentSchemaVersion < SCHEMA_VERSION) { - // Run schema update code. + // Run the schema update code. switch (currentSchemaVersion) { // Upgrade from schema version 0 to schema version 1. @@ -111,6 +111,7 @@ void DomainsDatabaseHelper::addDatabase() [[fallthrough]]; } + // Upgrade from schema version 4 to schema version 5. case 4: { // Add the Local Storage column. @@ -125,7 +126,7 @@ void DomainsDatabaseHelper::addDatabase() domainsDatabase.exec("PRAGMA user_version = " + QString::number(SCHEMA_VERSION)); } } - else + else // The domains table does not exist. { // Instantiate a create table query. QSqlQuery createTableQuery(domainsDatabase); @@ -160,7 +161,7 @@ void DomainsDatabaseHelper::addDatabase() } }; -QSqlQuery DomainsDatabaseHelper::getDomainQuery(const QString &hostname) +QSqlQuery DomainsDatabase::getDomainQuery(const QString &hostname) { // Get a handle for the domains database. QSqlDatabase domainsDatabase = QSqlDatabase::database(CONNECTION_NAME); @@ -184,8 +185,7 @@ QSqlQuery DomainsDatabaseHelper::getDomainQuery(const QString &hostname) while (allDomainNamesQuery.next()) { // Add the domain name and database ID to the map. - domainSettingsMap.insert(allDomainNamesQuery.record().field(DomainsDatabaseHelper::DOMAIN_NAME).value().toString(), - allDomainNamesQuery.record().field(DomainsDatabaseHelper::_ID).value().toInt()); + domainSettingsMap.insert(allDomainNamesQuery.record().field(DOMAIN_NAME).value().toString(), allDomainNamesQuery.record().field(_ID).value().toInt()); } // Initialize the database ID tracker. diff --git a/src/helpers/DomainsDatabaseHelper.h b/src/databases/DomainsDatabase.h similarity index 93% rename from src/helpers/DomainsDatabaseHelper.h rename to src/databases/DomainsDatabase.h index 50058db..a75b831 100644 --- a/src/helpers/DomainsDatabaseHelper.h +++ b/src/databases/DomainsDatabase.h @@ -17,17 +17,17 @@ * along with Privacy Browser PC. If not, see . */ -#ifndef DOMAINSDATABASEHELPER_H -#define DOMAINSDATABASEHELPER_H +#ifndef DOMAINSDATABASE_H +#define DOMAINSDATABASE_H // Qt framework headers. #include -class DomainsDatabaseHelper +class DomainsDatabase { public: // The default constructor. - DomainsDatabaseHelper(); + DomainsDatabase(); // The public functions. static void addDatabase(); diff --git a/src/dialogs/AddOrEditCookieDialog.cpp b/src/dialogs/AddOrEditCookieDialog.cpp index 78234a6..e39303e 100644 --- a/src/dialogs/AddOrEditCookieDialog.cpp +++ b/src/dialogs/AddOrEditCookieDialog.cpp @@ -20,6 +20,7 @@ // Application headers. #include "AddOrEditCookieDialog.h" #include "ui_AddOrEditCookieDialog.h" +#include "databases/CookiesDatabase.h" // KDE Framework headers. #include @@ -33,7 +34,7 @@ const int AddOrEditCookieDialog::AddCookie = 0; const int AddOrEditCookieDialog::EditCookie = 1; // Construct the class. -AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer) : QDialog(nullptr) +AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer, const bool &isDurable) : QDialog(nullptr) { // Set the dialog window title according to the dialog type. if (dialogType == AddCookie) @@ -41,8 +42,9 @@ AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetwo else setWindowTitle(i18nc("The edit cookie dialog window title.", "Edit Cookie")); - // Populate the is edit dialog boolean. + // Populate the class variables. isEditDialog = (dialogType == EditCookie); + originalIsDurable = isDurable; // Set the window modality. setWindowModality(Qt::WindowModality::ApplicationModal); @@ -56,6 +58,7 @@ AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetwo // Get handles for the widgets. domainLineEditPointer = addOrEditCookieDialogUi.domainLineEdit; nameLineEditPointer = addOrEditCookieDialogUi.nameLineEdit; + durableCheckBoxPointer = addOrEditCookieDialogUi.durableCheckBox; expirationCheckBoxPointer = addOrEditCookieDialogUi.expirationCheckBox; expirationDateTimeEditPointer = addOrEditCookieDialogUi.expirationDateTimeEdit; pathLineEditPointer = addOrEditCookieDialogUi.pathLineEdit; @@ -69,18 +72,19 @@ AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetwo if (isEditDialog) { // Store the old cookie. - oldCookie = *cookiePointer; + originalCookie = *cookiePointer; // Populate the widgets. - domainLineEditPointer->setText(oldCookie.domain()); - nameLineEditPointer->setText(oldCookie.name()); - pathLineEditPointer->setText(oldCookie.path()); - httpOnlyCheckBoxPointer->setChecked(oldCookie.isHttpOnly()); - secureCheckBoxPointer->setChecked(oldCookie.isSecure()); - valueLineEditPointer->setText(oldCookie.value()); + domainLineEditPointer->setText(originalCookie.domain()); + durableCheckBoxPointer->setChecked(originalIsDurable); + nameLineEditPointer->setText(originalCookie.name()); + pathLineEditPointer->setText(originalCookie.path()); + httpOnlyCheckBoxPointer->setChecked(originalCookie.isHttpOnly()); + secureCheckBoxPointer->setChecked(originalCookie.isSecure()); + valueLineEditPointer->setText(originalCookie.value()); // Populate the expiration date if it exists. - if (!oldCookie.isSessionCookie()) + if (!originalCookie.isSessionCookie()) { // Check the expiration box. expirationCheckBoxPointer->setChecked(true); @@ -89,7 +93,7 @@ AddOrEditCookieDialog::AddOrEditCookieDialog(const int &dialogType, const QNetwo expirationDateTimeEditPointer->setEnabled(true); // Set the expiration date. - expirationDateTimeEditPointer->setDateTime(oldCookie.expirationDate()); + expirationDateTimeEditPointer->setDateTime(originalCookie.expirationDate()); } } @@ -114,13 +118,13 @@ void AddOrEditCookieDialog::saveCookie() { // Delete the old cookie if this is an edit dialog. if (isEditDialog) - emit deleteCookie(oldCookie); + emit deleteCookie(originalCookie); // Create the variables. QNetworkCookie cookie; // Populate the cookie. - cookie.setDomain(domainLineEditPointer->text()); + cookie.setDomain(domainLineEditPointer->text().toLower()); cookie.setName(nameLineEditPointer->text().toUtf8()); cookie.setPath(pathLineEditPointer->text()); cookie.setHttpOnly(httpOnlyCheckBoxPointer->isChecked()); @@ -130,8 +134,37 @@ void AddOrEditCookieDialog::saveCookie() // Populate the expiration date if it is specified. if (expirationCheckBoxPointer->isChecked()) cookie.setExpirationDate(expirationDateTimeEditPointer->dateTime()); - // Add the cookie. - emit addCookie(cookie); + // Get the durable status. + const bool isDurable = durableCheckBoxPointer->isChecked(); + + // Update the durable cookies database. + if (originalIsDurable) // The cookie is currently in the durable cookies database. + { + if (isDurable) // Update the cookie in the database. + { + qDebug() << "Updating a durable cookie."; + + // Update the cookie in the durable cookies database. + CookiesDatabase::updateCookie(originalCookie, cookie); + } + else // Delete the cookie from the database. + { + qDebug() << "Deleting a durable cookie."; + + // Delete the cookie from the durable cookies database. + CookiesDatabase::deleteCookie(originalCookie); + } + } + else if (isDurable) // The cookie is being added to the durable cookies database. + { + qDebug() << "Adding a durable cookie."; + + // Add the cookie to the durable cookies database. + CookiesDatabase::addCookie(cookie); + } + + // Add the cookie to the store, the list, and the tree. + emit addCookie(cookie, isDurable); // Close the dialog. reject(); diff --git a/src/dialogs/AddOrEditCookieDialog.h b/src/dialogs/AddOrEditCookieDialog.h index 5bc763f..d00e3f7 100644 --- a/src/dialogs/AddOrEditCookieDialog.h +++ b/src/dialogs/AddOrEditCookieDialog.h @@ -33,7 +33,7 @@ class AddOrEditCookieDialog : public QDialog public: // The primary constructor. - explicit AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer = nullptr); + explicit AddOrEditCookieDialog(const int &dialogType, const QNetworkCookie *cookiePointer = nullptr, const bool &isDurable = false); // The public static constants. static const int AddCookie; @@ -41,7 +41,7 @@ public: signals: // The signals. - void addCookie(const QNetworkCookie &cookie) const; + void addCookie(const QNetworkCookie &cookie, const bool &isDurable) const; void deleteCookie(const QNetworkCookie &cookie) const; private Q_SLOTS: @@ -53,6 +53,7 @@ private Q_SLOTS: private: // The private widgets. QLineEdit *domainLineEditPointer; + QCheckBox *durableCheckBoxPointer; QCheckBox *expirationCheckBoxPointer; QDateTimeEdit *expirationDateTimeEditPointer; QCheckBox *httpOnlyCheckBoxPointer; @@ -63,7 +64,8 @@ private: QLineEdit *valueLineEditPointer; // The private variables. - QNetworkCookie oldCookie; bool isEditDialog; + QNetworkCookie originalCookie; + bool originalIsDurable; }; #endif diff --git a/src/dialogs/CookiesDialog.cpp b/src/dialogs/CookiesDialog.cpp index b200891..fa9679c 100644 --- a/src/dialogs/CookiesDialog.cpp +++ b/src/dialogs/CookiesDialog.cpp @@ -21,6 +21,7 @@ #include "AddOrEditCookieDialog.h" #include "CookiesDialog.h" #include "ui_CookiesDialog.h" +#include "databases/CookiesDatabase.h" // KDE Frameworks headers. #include @@ -117,30 +118,33 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe // Get a handle for the tree view. treeViewPointer = cookiesDialogUi.treeView; - // Initialize the standard item model. - standardItemModelPointer = new QStandardItemModel(); + // Initialize the tree model. + treeModelPointer = new QStandardItemModel(); // Set the column count. - standardItemModelPointer->setColumnCount(6); - - // Set the header data. - standardItemModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name")); - standardItemModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Path header.", "Path")); - standardItemModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date")); - standardItemModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only")); - standardItemModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure")); - standardItemModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Value header.", "Value")); - - // Set the header tool tips. - standardItemModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.", + treeModelPointer->setColumnCount(7); + + // Set the tree header data. + treeModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name")); + treeModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Durable header.", "Durable")); + treeModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Path header.", "Path")); + treeModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date")); + treeModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only")); + treeModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure")); + treeModelPointer->setHeaderData(6, Qt::Horizontal, i18nc("The cookie Value header.", "Value")); + + // Set the tree header tool tips. + treeModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.", "The name identifies the cookie. Each cookie has a unique combination of domain, name, and path.")); - standardItemModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL.")); - standardItemModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Expiration Date tool tip.", + treeModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Durable tool tip", + "Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date.")); + treeModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL.")); + treeModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie Expiration Date tool tip.", "Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes.")); - standardItemModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie HTTP Only tool tip.", + treeModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie HTTP Only tool tip.", "Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks.")); - standardItemModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP).")); - standardItemModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data.")); + treeModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP).")); + treeModelPointer->horizontalHeaderItem(6)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data.")); // Sort the cookie list. cookieListPointer->sort(cookieSortPredicate); @@ -148,10 +152,10 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe // Create the current domain string. QString currentDomainString = ""; - // Create the current domain standard item pointer. - QStandardItem *currentDomainStandardItemPointer; + // Create the current domain item pointer. + QStandardItem *currentDomainItemPointer; - // Populate the VBoxLayout. + // Populate the cookie tree view. for (QNetworkCookie cookie : *cookieListPointer) { // Get the cookie domain. @@ -160,72 +164,45 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe // Check to see if the cookie is a member of the current domain. if (cookieDomain != currentDomainString) // Create a new domain in the tree. { - // Create a list for the domain standard items. - QList domainStandardItemList; - - // Create the new domain standard items. - QStandardItem *domainStandardItemPointer = new QStandardItem(cookieDomain); - QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral("")); - - // Disable editing of the domain. - domainStandardItemPointer->setEditable(false); - pathStandardItemPointer->setEditable(false); - expirationDateStandardItemPointer->setEditable(false); - isHttpOnlyStandardItemPointer->setEditable(false); - isSecureStandardItemPointer->setEditable(false); - valueStandardItemPointer->setEditable(false); - - // Populate the domain standard item list. - domainStandardItemList.append(domainStandardItemPointer); - domainStandardItemList.append(pathStandardItemPointer); - domainStandardItemList.append(expirationDateStandardItemPointer); - domainStandardItemList.append(isHttpOnlyStandardItemPointer); - domainStandardItemList.append(isSecureStandardItemPointer); - domainStandardItemList.append(valueStandardItemPointer); + // Create the domain name item. + QStandardItem *domainNameItemPointer = new QStandardItem(cookieDomain); // Add the domain to the tree. - standardItemModelPointer->invisibleRootItem()->appendRow(domainStandardItemList); + treeModelPointer->invisibleRootItem()->appendRow(domainNameItemPointer); // Update the current domain string. currentDomainString = cookieDomain; - // Update the current domain standard item pointer. - currentDomainStandardItemPointer = domainStandardItemPointer; + // Update the current domain item pointer. + currentDomainItemPointer = domainNameItemPointer; } - // Create a list for the cookie standard items. - QList cookieStandardItemList; - - // Create the cookie standard items. - QStandardItem *nameStandardItemPointer = new QStandardItem(QString(cookie.name())); - QStandardItem *pathStandardItemPointer = new QStandardItem(QString(cookie.path())); - QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString())); - QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no"))); - QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no"))); - QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value())); - - // Disable editing of the cookie standard items. - nameStandardItemPointer->setEditable(false); - pathStandardItemPointer->setEditable(false); - expirationDateStandardItemPointer->setEditable(false); - isHttpOnlyStandardItemPointer->setEditable(false); - isSecureStandardItemPointer->setEditable(false); - valueStandardItemPointer->setEditable(false); + // Check to see if the cookie is durable. + bool isDurable = CookiesDatabase::isDurable(cookie); + + // Create a list for the cookie items. + QList cookieItemList; + + // Create the cookie items. + QStandardItem *nameItemPointer = new QStandardItem(QString(cookie.name())); + QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no"))); + QStandardItem *pathItemPointer = new QStandardItem(QString(cookie.path())); + QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString())); + QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no"))); + QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no"))); + QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value())); // Populate the cookie standard item list. - cookieStandardItemList.append(nameStandardItemPointer); - cookieStandardItemList.append(pathStandardItemPointer); - cookieStandardItemList.append(expirationDateStandardItemPointer); - cookieStandardItemList.append(isHttpOnlyStandardItemPointer); - cookieStandardItemList.append(isSecureStandardItemPointer); - cookieStandardItemList.append(valueStandardItemPointer); + cookieItemList.append(nameItemPointer); + cookieItemList.append(durableItemPointer); + cookieItemList.append(pathItemPointer); + cookieItemList.append(expirationDateItemPointer); + cookieItemList.append(isHttpOnlyItemPointer); + cookieItemList.append(isSecureItemPointer); + cookieItemList.append(valueItemPointer); // Add the cookie to the tree. - currentDomainStandardItemPointer->appendRow(cookieStandardItemList); + currentDomainItemPointer->appendRow(cookieItemList); } // Auto resize the headers. @@ -240,14 +217,17 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe // Indicate that all the rows are the same height, wich improves performance. treeViewPointer->setUniformRowHeights(true); - // Set the tree view model. - treeViewPointer->setModel(standardItemModelPointer); + // Disable editing. + treeViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers); + + // Set the tree model. + treeViewPointer->setModel(treeModelPointer); - // Get a handle for the tree view selection model. - treeViewSelectionModelPointer = treeViewPointer->selectionModel(); + // Get a handle for the tree selection model. + treeSelectionModelPointer = treeViewPointer->selectionModel(); // Listen for selection changes. - connect(treeViewSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi())); + connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi())); // Get handles for the buttons. addCookieButtonPointer = cookiesDialogUi.addCookieButton; @@ -297,7 +277,7 @@ CookiesDialog::CookiesDialog(std::list *originalCookieListPointe updateUi(); }; -void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const +void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const { // Add the cookie to the cookie list and the cookie store. emit addCookie(cookie); @@ -306,46 +286,22 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const QString newDomain = cookie.domain(); // Check to see if the domain already exists in the model. - QList currentDomainStandardItemList = standardItemModelPointer->findItems(newDomain); + QList currentDomainItemList = treeModelPointer->findItems(newDomain); - // Create a domain standard item pointer. - QStandardItem *domainStandardItemPointer; + // Create a domain item pointer. + QStandardItem *domainNameItemPointer; - // Prepare the domain standard item pointer. - if (currentDomainStandardItemList.isEmpty()) // The domain doesn't currently exist in the tree. + // Prepare the domain item pointer. + if (currentDomainItemList.isEmpty()) // The domain doesn't currently exist in the tree. { - // Create a list for the domain standard items. - QList domainStandardItemList; - - // Create the new domain standard items. - domainStandardItemPointer = new QStandardItem(newDomain); - QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral("")); - QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral("")); - - // Disable editing of the domain. - domainStandardItemPointer->setEditable(false); - pathStandardItemPointer->setEditable(false); - expirationDateStandardItemPointer->setEditable(false); - isHttpOnlyStandardItemPointer->setEditable(false); - isSecureStandardItemPointer->setEditable(false); - valueStandardItemPointer->setEditable(false); - - // Populate the domain standard item list. - domainStandardItemList.append(domainStandardItemPointer); - domainStandardItemList.append(pathStandardItemPointer); - domainStandardItemList.append(expirationDateStandardItemPointer); - domainStandardItemList.append(isHttpOnlyStandardItemPointer); - domainStandardItemList.append(isSecureStandardItemPointer); - domainStandardItemList.append(valueStandardItemPointer); + // Create the domain name item. + domainNameItemPointer = new QStandardItem(newDomain); // Create the insert domain row number. int insertDomainRowNumber = 0; // Get the number of domains in the tree. - int numberOfDomains = standardItemModelPointer->invisibleRootItem()->rowCount(); + int numberOfDomains = treeModelPointer->invisibleRootItem()->rowCount(); // Get the new domain strings. QString newDomainTopLevelDomain = newDomain.section('.', -1); @@ -356,7 +312,7 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const for (int i = 0; i < numberOfDomains; ++i) { // Get the current domain strings. - QString currentDomain = standardItemModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString(); + QString currentDomain = treeModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString(); QString currentDomainTopLevelDomain = currentDomain.section('.', -1); QString currentDomainSecondLevelDomain = currentDomain.section('.', -2); QString currentDomainThirdLevelDomain = currentDomain.section('.', -3); @@ -385,76 +341,85 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const } // Add the domain to the tree. - standardItemModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainStandardItemList); + treeModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainNameItemPointer); } else // The domain already exists in the tree. { // Use the current domain standard item. - domainStandardItemPointer = currentDomainStandardItemList[0]; + domainNameItemPointer = currentDomainItemList[0]; } // Get strings for the new cookie name and path (used later in the placement of the row). QString newCookieName = QString(cookie.name()); QString newCookiePath = QString(cookie.path()); - // Create a list for the cookie standard items. - QList cookieStandardItemList; - - // Create the cookie standard items. - QStandardItem *nameStandardItemPointer = new QStandardItem(newCookieName); - QStandardItem *pathStandardItemPointer = new QStandardItem(newCookiePath); - QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString())); - QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no"))); - QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no"))); - QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value())); - - // Disable editing of the cookie standard items. - nameStandardItemPointer->setEditable(false); - pathStandardItemPointer->setEditable(false); - expirationDateStandardItemPointer->setEditable(false); - isHttpOnlyStandardItemPointer->setEditable(false); - isSecureStandardItemPointer->setEditable(false); - valueStandardItemPointer->setEditable(false); - - // Populate the cookie standard item list. - cookieStandardItemList.append(nameStandardItemPointer); - cookieStandardItemList.append(pathStandardItemPointer); - cookieStandardItemList.append(expirationDateStandardItemPointer); - cookieStandardItemList.append(isHttpOnlyStandardItemPointer); - cookieStandardItemList.append(isSecureStandardItemPointer); - cookieStandardItemList.append(valueStandardItemPointer); + // Create a cookie item list. + QList cookieItemList; + + // Create the cookie items. + QStandardItem *nameItemPointer = new QStandardItem(newCookieName); + QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no"))); + QStandardItem *pathItemPointer = new QStandardItem(newCookiePath); + QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString())); + QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no"))); + QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no"))); + QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value())); + + // Populate the cookie item list. + cookieItemList.append(nameItemPointer); + cookieItemList.append(durableItemPointer); + cookieItemList.append(pathItemPointer); + cookieItemList.append(expirationDateItemPointer); + cookieItemList.append(isHttpOnlyItemPointer); + cookieItemList.append(isSecureItemPointer); + cookieItemList.append(valueItemPointer); // Create the insert cookie row number. int insertCookieRowNumber = 0; + // Create the remove existing row tracker. + bool removeExistingRow = false; + // Get the number of cookies in the domain. - int numberOfCookies = domainStandardItemPointer->rowCount(); + int numberOfCookies = domainNameItemPointer->rowCount(); // Iterate through the cookies for this domain. for (int i = 0; i < numberOfCookies; ++i) { // Get the current cookie name and path at the indicated row. - QString currentCookieName = domainStandardItemPointer->child(i, 0)->index().data().toString(); - QString currentCookiePath = domainStandardItemPointer->child(i, 1)->index().data().toString(); + QString currentCookieName = domainNameItemPointer->child(i, 0)->index().data().toString(); + QString currentCookiePath = domainNameItemPointer->child(i, 2)->index().data().toString(); // Check to see if the new cookie should be inserted after the current cookie. - if (newCookieName > currentCookieName) + if (newCookieName > currentCookieName) // The new cookie name comes after the current cookie name. { // Insert the new cookie after the current cookie. insertCookieRowNumber = i + 1; } - else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath)) + else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath)) // The names are the same, but the new cookie path comes after the current cookie path. { // Insert the new cookie after the current cookie. insertCookieRowNumber = i + 1; } + else if ((newCookieName == currentCookieName) && (newCookiePath == currentCookiePath)) // The cookies are the same. + { + // Remove the existing cookie in this row. + removeExistingRow = true; + + // Insert the cookie in it's place. + insertCookieRowNumber = i; + } } - // Add the cookie to the tree. - domainStandardItemPointer->insertRow(insertCookieRowNumber, cookieStandardItemList); + // Remove the existing row if it is being edited. + if (removeExistingRow) + domainNameItemPointer->removeRow(insertCookieRowNumber); + + // Add the cookie to the tree model. + domainNameItemPointer->insertRow(insertCookieRowNumber, cookieItemList); // Get the new cookie model index. - QModelIndex newCookieIndex = nameStandardItemPointer->index(); + QModelIndex newCookieIndex = nameItemPointer->index(); // Set the new cookie to be the current index. treeViewPointer->setCurrentIndex(newCookieIndex); @@ -463,7 +428,7 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const treeViewPointer->expand(newCookieIndex.parent()); } -void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const +void CookiesDialog::deleteCookie(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const { // Create a partial cookie. QNetworkCookie partialCookie; @@ -471,40 +436,69 @@ void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const // Populate the partial cookie from the current model index. partialCookie.setDomain(modelIndex.parent().siblingAtColumn(0).data().toString()); partialCookie.setName(modelIndex.siblingAtColumn(0).data().toString().toUtf8()); - partialCookie.setPath(modelIndex.siblingAtColumn(1).data().toString()); + partialCookie.setPath(modelIndex.siblingAtColumn(2).data().toString()); // Create a cookie to delete. QNetworkCookie cookieToDelete; - // Search for the partial cookie in the cookie list. - for (QNetworkCookie cookie : *cookieListPointer) + // Check if the cookie is durable. + bool isDurable = CookiesDatabase::isDurable(partialCookie); + + // Only delete durable cookies if directed. + if (deleteDurableCookies || !isDurable) { - // Store the cookie to delete if it has the same identifier as the partial cookie. - if (cookie.hasSameIdentifier(partialCookie)) - cookieToDelete = cookie; + // Search for the partial cookie in the cookie list. + for (QNetworkCookie cookie : *cookieListPointer) + { + // Store the cookie to delete if it has the same identifier as the partial cookie. + if (cookie.hasSameIdentifier(partialCookie)) + cookieToDelete = cookie; + } + + // Remove the cookie from the tree model. + treeModelPointer->removeRow(modelIndex.row(), modelIndex.parent()); + + // Delete the cookie from the cookie list and cookie store. + emit deleteCookie(cookieToDelete); + + // Delete the cookie from the durable cookies database. + if (isDurable) + CookiesDatabase::deleteCookie(cookieToDelete); } +} - // Remove the cookie from the tree view. - standardItemModelPointer->removeRow(modelIndex.row(), modelIndex.parent()); +void CookiesDialog::deleteDomain(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const +{ + // Get the parent index. + QModelIndex parentIndex = modelIndex.parent(); - // Delete the cookie from the cookie list and cookie store. - emit deleteCookie(cookieToDelete); + // Get the number of cookies in the domain. + int numberOfCookies = treeModelPointer->rowCount(modelIndex); + + // Delete each child cookie, starting from the bottom. + for (int i = numberOfCookies; i > 0; --i) + deleteCookie(treeModelPointer->index(i-1, 0, modelIndex), deleteDurableCookies); + + // Remove the domain if all the cookies have been deleted. + if (treeModelPointer->rowCount(modelIndex) == 0) + treeModelPointer->removeRow(modelIndex.row(), parentIndex); } + void CookiesDialog::deleteCookieFromDialog(const QNetworkCookie &cookie) const { // Get the current model index. - QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex(); + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex(); // Get the parent index. QModelIndex parentIndex = currentIndex.parent(); - // Remove the cookie from the tree view. - standardItemModelPointer->removeRow(currentIndex.row(), parentIndex); + // Remove the cookie from the tree model. + treeModelPointer->removeRow(currentIndex.row(), parentIndex); - // Remove the domain from the tree view if its only cookie has been deleted. - if (standardItemModelPointer->rowCount(parentIndex) == 0) - standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent()); + // Remove the domain from the tree model if its only cookie has been deleted. + if (treeModelPointer->rowCount(parentIndex) == 0) + treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent()); // Delete the cookie from the cookie list and cookie store. emit deleteCookie(cookie); @@ -519,7 +513,7 @@ void CookiesDialog::showAddCookieDialog() const addCookieDialogPointer->show(); // Add the cookie if directed. - connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie))); + connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool))); } void CookiesDialog::showDeleteAllMessageBox() const @@ -536,6 +530,12 @@ void CookiesDialog::showDeleteAllMessageBox() const // Set the text. deleteAllCookiesMessageBox.setText(i18nc("Delete all cookies dialog text", "Delete all cookies?")); + // Create a delete durable cookies check box. + QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable")); + + // Add the check box to the dialog. + deleteAllCookiesMessageBox.setCheckBox(&deleteDurableCookiesCheckBox); + // Set the standard buttons. deleteAllCookiesMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); @@ -548,27 +548,43 @@ void CookiesDialog::showDeleteAllMessageBox() const // Delete all cookies if instructed. if (returnValue == QMessageBox::Yes) { - // Delete all the cookies. - emit deleteAllCookies(); + // Only delete durable cookies if requested. + if (deleteDurableCookiesCheckBox.isChecked()) // Delete everything. + { + // Delete all the cookies. + emit deleteAllCookies(); + + // Clear the tree model. + treeModelPointer->clear(); + + // Delete the durable cookies from the database. + CookiesDatabase::deleteAllCookies(); + + // Update the UI. + updateUi(); + } + else // Only delete cookies that are not durable. + { + // Get the root model index. + QModelIndex rootIndex = treeModelPointer->invisibleRootItem()->index(); - // Clear the standard item model. - standardItemModelPointer->clear(); + // Get the number of domains. + int numberOfDomains = treeModelPointer->rowCount(rootIndex); - // Update the UI. - updateUi(); + // Delete each domain, starting from the bottom. + for (int i = numberOfDomains; i > 0; --i) + deleteDomain(treeModelPointer->index(i - 1, 0, rootIndex), deleteDurableCookiesCheckBox.isChecked()); + } } } void CookiesDialog::showDeleteCookieMessageBox() const { // Get the current model index. - QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex(); - - // Get the parent model index. - QModelIndex parentIndex = currentIndex.parent(); + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex(); // Determine if a domain is selected. - bool isDomain = standardItemModelPointer->hasChildren(currentIndex); + bool isDomain = treeModelPointer->hasChildren(currentIndex); // Instantiate a delete cookie message box. QMessageBox deleteCookieMessageBox; @@ -576,26 +592,35 @@ void CookiesDialog::showDeleteCookieMessageBox() const // Set the icon. deleteCookieMessageBox.setIcon(QMessageBox::Warning); - if (isDomain) + // Create a delete durable cookies check box. + QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable")); + + if (isDomain) // A domain is selected. { // Get the number of cookies. - int numberOfCookiesToDelete = standardItemModelPointer->rowCount(currentIndex); + int numberOfCookiesToDelete = treeModelPointer->rowCount(currentIndex); // Set the window title. - deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookies dialog title", "Delete %1 Cookies", numberOfCookiesToDelete)); + deleteCookieMessageBox.setWindowTitle(i18ncp("Delete cookies dialog title", "Delete %1 Cookie", "Delete 1% Cookies", numberOfCookiesToDelete)); // Set the text. - deleteCookieMessageBox.setText(i18nc("Delete cookies dialog text", "Delete %1 cookies?", numberOfCookiesToDelete)); + deleteCookieMessageBox.setText(i18ncp("Delete cookies dialog text", "Delete %1 cookie?", "Delete %1 cookies?", numberOfCookiesToDelete)); } - else + else // A single cookie is selected. { // Set the window title. deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookie dialog title", "Delete 1 Cookie")); // Set the text. deleteCookieMessageBox.setText(i18nc("Delete cookie dialog text", "Delete 1 cookie?")); + + // Check the box. + deleteDurableCookiesCheckBox.setChecked(true); } + // Add the check box to the dialog. + deleteCookieMessageBox.setCheckBox(&deleteDurableCookiesCheckBox); + // Set the standard buttons. deleteCookieMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); @@ -611,27 +636,20 @@ void CookiesDialog::showDeleteCookieMessageBox() const // Delete the cookies according to the selection. if (isDomain) // A domain is selected. { - // Get the number of cookies. - int numberOfCookies = standardItemModelPointer->rowCount(currentIndex); - - // Delete each child cookie. - for (int i = 0; i < numberOfCookies; ++i) - { - // Delete the cookie for the first child. Once this is deleted, the second child will become the first child. - deleteCookie(standardItemModelPointer->index(0, 0, currentIndex)); - } - - // Delete the domain from the tree view. - standardItemModelPointer->removeRow(currentIndex.row(), parentIndex); + // Delete the domain. + deleteDomain(currentIndex, deleteDurableCookiesCheckBox.isChecked()); } else // A single cookie is selected. { + // Get the parent model index. + QModelIndex parentIndex = currentIndex.parent(); + // Delete the cookie. - deleteCookie(currentIndex); + deleteCookie(currentIndex, deleteDurableCookiesCheckBox.isChecked()); // Remove the domain row if its only cookie has been deleted. - if (standardItemModelPointer->rowCount(parentIndex) == 0) - standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent()); + if (treeModelPointer->rowCount(parentIndex) == 0) + treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent()); } } } @@ -639,7 +657,7 @@ void CookiesDialog::showDeleteCookieMessageBox() const void CookiesDialog::showEditCookieDialog() const { // Get the current model index. - QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex(); + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex(); // Create a partial cookie. QNetworkCookie partialCookie; @@ -647,7 +665,7 @@ void CookiesDialog::showEditCookieDialog() const // Populate the partial cookie from the current model index. partialCookie.setDomain(currentIndex.parent().siblingAtColumn(0).data().toString()); partialCookie.setName(currentIndex.siblingAtColumn(0).data().toString().toUtf8()); - partialCookie.setPath(currentIndex.siblingAtColumn(1).data().toString()); + partialCookie.setPath(currentIndex.siblingAtColumn(2).data().toString()); // Create a cookie to edit. QNetworkCookie cookieToEdit; @@ -661,33 +679,33 @@ void CookiesDialog::showEditCookieDialog() const } // Instantiate an edit cookie dialog. - QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit); + QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit, currentIndex.siblingAtColumn(1).data().toString() == i18n("yes")); // Show the dialog. editCookieDialogPointer->show(); // Process cookie events. - connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie))); + connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool))); connect(editCookieDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), this, SLOT(deleteCookieFromDialog(QNetworkCookie))); } void CookiesDialog::updateUi() const { // Get the current index of the first column. - QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex().siblingAtColumn(0); + QModelIndex currentIndex = treeSelectionModelPointer->currentIndex().siblingAtColumn(0); // Set the status of the buttons. - editCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection() && !standardItemModelPointer->hasChildren(currentIndex)); - deleteCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection());; - deleteAllButtonPointer->setEnabled(standardItemModelPointer->hasChildren(standardItemModelPointer->invisibleRootItem()->index())); + editCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection() && !treeModelPointer->hasChildren(currentIndex)); + deleteCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection());; + deleteAllButtonPointer->setEnabled(treeModelPointer->hasChildren(treeModelPointer->invisibleRootItem()->index())); // Update the delete cookie button text. if (deleteCookieButtonPointer->isEnabled()) // The button is enabled. { - if (standardItemModelPointer->hasChildren(currentIndex)) // A domain is selected. + if (treeModelPointer->hasChildren(currentIndex)) // A domain is selected. { // Update the button text. - deleteCookieButtonPointer->setText(i18nc("Delete cookies button.", "&Delete %1 cookies", standardItemModelPointer->rowCount(currentIndex))); + deleteCookieButtonPointer->setText(i18ncp("Delete cookies button.", "&Delete %1 cookie", "&Delete %1 cookies", treeModelPointer->rowCount(currentIndex))); } else // A single cookie is selected. { diff --git a/src/dialogs/CookiesDialog.h b/src/dialogs/CookiesDialog.h index f34beca..89c2be4 100644 --- a/src/dialogs/CookiesDialog.h +++ b/src/dialogs/CookiesDialog.h @@ -47,7 +47,7 @@ signals: private Q_SLOTS: // The private slots. - void addCookieFromDialog(const QNetworkCookie &cookie) const; + void addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const; void deleteCookieFromDialog(const QNetworkCookie &cookie) const; void showAddCookieDialog() const; void showDeleteAllMessageBox() const; @@ -57,16 +57,17 @@ private Q_SLOTS: private: // The private variables. - QItemSelectionModel *treeViewSelectionModelPointer; QPushButton *addCookieButtonPointer; std::list *cookieListPointer; QPushButton *deleteAllButtonPointer; QPushButton *deleteCookieButtonPointer; QPushButton *editCookieButtonPointer; - QStandardItemModel *standardItemModelPointer; + QStandardItemModel *treeModelPointer; + QItemSelectionModel *treeSelectionModelPointer; QTreeView *treeViewPointer; // The private functions. - void deleteCookie(const QModelIndex &modelIndex) const; + void deleteCookie(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const; + void deleteDomain(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const; }; #endif diff --git a/src/dialogs/DomainSettingsDialog.cpp b/src/dialogs/DomainSettingsDialog.cpp index 151a0b4..76477ec 100644 --- a/src/dialogs/DomainSettingsDialog.cpp +++ b/src/dialogs/DomainSettingsDialog.cpp @@ -21,7 +21,7 @@ #include "DomainSettingsDialog.h" #include "Settings.h" #include "ui_DomainSettingsDialog.h" -#include "helpers/DomainsDatabaseHelper.h" +#include "databases/DomainsDatabase.h" #include "helpers/UserAgentHelper.h" // Qt toolkit headers. @@ -70,10 +70,10 @@ DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString & resetButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::StandardButton::Reset); // Create a table model. - domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabaseHelper::CONNECTION_NAME)); + domainsTableModelPointer = new QSqlTableModel(nullptr, QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME)); // Set the table for the model. - domainsTableModelPointer->setTable(DomainsDatabaseHelper::DOMAINS_TABLE); + domainsTableModelPointer->setTable(DomainsDatabase::DOMAINS_TABLE); // Set the edit strategy to be manual. domainsTableModelPointer->setEditStrategy(QSqlTableModel::EditStrategy::OnManualSubmit); @@ -102,7 +102,7 @@ DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString & case SHOW_ALL_DOMAINS: { // Select the first entry in the list view. - domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME))); + domainsListViewPointer->setCurrentIndex(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME))); // Populate the domain settings. domainSelected(domainsSelectionModelPointer->currentIndex()); @@ -121,8 +121,8 @@ DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString & case EDIT_DOMAIN: { // Find the index for the new domain. `1` returns the first match. - QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)), - Qt::DisplayRole, domainName, 1, Qt::MatchWrap); + QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)), + Qt::DisplayRole, domainName, 1, Qt::MatchWrap); // Move to the new domain. domainsListViewPointer->setCurrentIndex(newDomainIndex[0]); @@ -161,15 +161,15 @@ DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString & void DomainSettingsDialog::addDomain(const QString &domainName) const { // Create a new domain record. - QSqlRecord newDomainRecord = QSqlDatabase::database(DomainsDatabaseHelper::CONNECTION_NAME).record(DomainsDatabaseHelper::DOMAINS_TABLE); + QSqlRecord newDomainRecord = QSqlDatabase::database(DomainsDatabase::CONNECTION_NAME).record(DomainsDatabase::DOMAINS_TABLE); // Set the values for the new domain. - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME), domainName); - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT), DomainsDatabaseHelper::SYSTEM_DEFAULT); - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE), DomainsDatabaseHelper::SYSTEM_DEFAULT); - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT), UserAgentHelper::SYSTEM_DEFAULT_DATABASE); - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR), DomainsDatabaseHelper::SYSTEM_DEFAULT); - newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR), 1.0); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME), domainName); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT), DomainsDatabase::SYSTEM_DEFAULT); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE), DomainsDatabase::SYSTEM_DEFAULT); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT), UserAgentHelper::SYSTEM_DEFAULT_DATABASE); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR), DomainsDatabase::SYSTEM_DEFAULT); + newDomainRecord.setValue(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR), 1.0); // Insert the new domain. `-1` appends it to the end. domainsTableModelPointer->insertRecord(-1, newDomainRecord); @@ -178,8 +178,8 @@ void DomainSettingsDialog::addDomain(const QString &domainName) const domainsTableModelPointer->submitAll(); // Find the index for the new domain. `-1` allows for multiple entries to be returned. - QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME)), - Qt::DisplayRole, domainName, -1, Qt::MatchWrap); + QModelIndexList newDomainIndex = domainsTableModelPointer->match(domainsTableModelPointer->index(0, domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME)), + Qt::DisplayRole, domainName, -1, Qt::MatchWrap); // Move to the new domain. If there are multiple domains with the same name, the new one should be the last in the list. domainsListViewPointer->setCurrentIndex(newDomainIndex[newDomainIndex.size() - 1]); @@ -197,17 +197,17 @@ void DomainSettingsDialog::apply() const QModelIndex currentIndex = domainsListViewPointer->currentIndex(); // Get the ID of the current index row. - QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::_ID)).data(); + QVariant currentId = currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::_ID)).data(); // Submit all pending changes. domainsTableModelPointer->submitAll(); // Find the new index for the selected id. The `1` keeps searching after the first match. - QModelIndexList newIndexList = domainsTableModelPointer->match(currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::_ID)), Qt::DisplayRole, currentId, + QModelIndexList newIndexList = domainsTableModelPointer->match(currentIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::_ID)), Qt::DisplayRole, currentId, 1, Qt::MatchWrap); // Select the new index. - domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOMAIN_NAME))); + domainsListViewPointer->setCurrentIndex(newIndexList[0].siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOMAIN_NAME))); // Update the UI. updateUi(); @@ -228,7 +228,7 @@ void DomainSettingsDialog::cancel() void DomainSettingsDialog::customZoomFactorChanged(const double &newValue) const { // Update the domains table model. - domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)), newValue); + domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)), newValue); // Update the UI. updateUi(); @@ -237,7 +237,7 @@ void DomainSettingsDialog::customZoomFactorChanged(const double &newValue) const void DomainSettingsDialog::domStorageChanged(const int &newIndex) const { // Update the domains table model. - domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE)), newIndex); + domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)), newIndex); // Populate the DOM storage label. populateDomStorageLabel(); @@ -261,16 +261,16 @@ void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const domainNameLineEditPointer->setText(modelIndex.data().toString()); // Populate the JavaScript combo box. - javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT)).data().toInt()); + javaScriptComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)).data().toInt()); // Populate the local storage combo box. - localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::LOCAL_STORAGE)).data().toInt()); + localStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)).data().toInt()); // Populate the DOM storage combo box. - domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::DOM_STORAGE)).data().toInt()); + domStorageComboBoxPointer->setCurrentIndex(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::DOM_STORAGE)).data().toInt()); // Get the user agent string. - QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT)).data().toString(); + QString userAgent = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)).data().toString(); // Get the user agent index. int userAgentIndex = UserAgentHelper::getDomainSettingsUserAgentIndex(userAgent); @@ -282,7 +282,7 @@ void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const if (userAgentIndex == -1) userAgentComboBoxPointer->setCurrentText(userAgent); // Get the zoom factor combo box index. - int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR)).data().toInt(); + int zoomFactorComboBoxIndex = modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)).data().toInt(); // Populate the zoom factor combo box. zoomFactorComboBoxPointer->setCurrentIndex(zoomFactorComboBoxIndex); @@ -296,7 +296,7 @@ void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const else // Custom zoom factor is selected. { // Display the custom zoom factor from the domain settings. - customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)).data().toDouble()); + customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble()); } // Set the initial status of the custom zoom factor spin box. @@ -315,7 +315,7 @@ void DomainSettingsDialog::domainSelected(const QModelIndex &modelIndex) const void DomainSettingsDialog::javaScriptChanged(const int &newIndex) const { // Update the domains table model. - domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::JAVASCRIPT)), newIndex); + domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::JAVASCRIPT)), newIndex); // Populate the JavaScript label. populateJavaScriptLabel(); @@ -327,7 +327,7 @@ void DomainSettingsDialog::javaScriptChanged(const int &newIndex) const void DomainSettingsDialog::localStorageChanged(const int &newIndex) const { // Update the domains table model. - domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::LOCAL_STORAGE)), newIndex); + domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::LOCAL_STORAGE)), newIndex); // Poplate the local storage label. populateLocalStorageLabel(); @@ -354,7 +354,7 @@ void DomainSettingsDialog::populateDomStorageLabel() const switch (domStorageComboBoxPointer->currentIndex()) { // Set the text according to the system default. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { if (Settings::domStorageEnabled()) domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label.", "DOM storage enabled")); @@ -365,7 +365,7 @@ void DomainSettingsDialog::populateDomStorageLabel() const } // Set the disabled text in bold. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label. The tags should be retained.", "DOM storage disabled")); @@ -373,7 +373,7 @@ void DomainSettingsDialog::populateDomStorageLabel() const } // Set the enabled text in bold. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { domStorageLabelPointer->setText(i18nc("Domain settings DOM storage label. The tags should be retained.", "DOM storage enabled")); @@ -388,7 +388,7 @@ void DomainSettingsDialog::populateJavaScriptLabel() const switch (javaScriptComboBoxPointer->currentIndex()) { // Set the text according to the system default. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { if (Settings::javaScriptEnabled()) javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label.", "JavaScript enabled")); @@ -399,7 +399,7 @@ void DomainSettingsDialog::populateJavaScriptLabel() const } // Set the disabled text in bold. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label. The tags should be retained.", "JavaScript disabled")); @@ -407,7 +407,7 @@ void DomainSettingsDialog::populateJavaScriptLabel() const } // Set the enabled text in bold. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { javaScriptLabelPointer->setText(i18nc("Domain settings JavaScript label. The tags should be retained.", "JavaScript enabled")); @@ -422,7 +422,7 @@ void DomainSettingsDialog::populateLocalStorageLabel() const switch (localStorageComboBoxPointer->currentIndex()) { // Set the text according to the system default. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { if (Settings::localStorageEnabled()) localStorageLabelPointer->setText(i18nc("Domain settings local storage label.", "Local storage enabled")); @@ -433,7 +433,7 @@ void DomainSettingsDialog::populateLocalStorageLabel() const } // Set the disabled text in bold. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { localStorageLabelPointer->setText(i18nc("Domain settings local storage label. The tags should be retained.", "Local storage disabled")); @@ -441,7 +441,7 @@ void DomainSettingsDialog::populateLocalStorageLabel() const } // Set the enabled text in bold. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { localStorageLabelPointer->setText(i18nc("Domain settings local storage label. The tabs should be retained.", "Local storage enabled")); @@ -574,7 +574,7 @@ void DomainSettingsDialog::updateUi() const void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) const { // Update the domains table model. - domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::USER_AGENT)), + domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)), UserAgentHelper::getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent)); // Populate the user agent label. @@ -590,7 +590,7 @@ void DomainSettingsDialog::zoomFactorComboBoxChanged(const int &newIndex) const QModelIndex modelIndex = domainsSelectionModelPointer->currentIndex(); // Update the domains table model. - domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::ZOOM_FACTOR)), newIndex); + domainsTableModelPointer->setData(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::ZOOM_FACTOR)), newIndex); // Populate the custom zoom factor spin box according to the zoom factor combo box. if (newIndex == 0) // System default zoom factor is selected. @@ -601,7 +601,7 @@ void DomainSettingsDialog::zoomFactorComboBoxChanged(const int &newIndex) const else // Custom zoom factor is selected. { // Display the custom zoom factor from the domain settings. - customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabaseHelper::CUSTOM_ZOOM_FACTOR)).data().toDouble()); + customZoomFactorSpinBoxPointer->setValue(modelIndex.siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::CUSTOM_ZOOM_FACTOR)).data().toDouble()); } // Update the status of the custom zoom factor spin box. diff --git a/src/helpers/CMakeLists.txt b/src/helpers/CMakeLists.txt index df368ac..042c5c3 100644 --- a/src/helpers/CMakeLists.txt +++ b/src/helpers/CMakeLists.txt @@ -18,7 +18,6 @@ # List the sources to include in the executable. target_sources(privacy-browser PRIVATE - DomainsDatabaseHelper.cpp SearchEngineHelper.cpp UserAgentHelper.cpp ) diff --git a/src/main.cpp b/src/main.cpp index 6aa5c51..10ce579 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,8 @@ */ // Application headers. -#include "helpers/DomainsDatabaseHelper.h" +#include "databases/CookiesDatabase.h" +#include "databases/DomainsDatabase.h" #include "windows/BrowserWindow.h" // KDE Frameworks headers. @@ -80,8 +81,9 @@ int main(int argc, char *argv[]) // Register with D-Bus, allowing multiple instances and allowing the program to run if for some reason the registration fails. KDBusService appDBusService(KDBusService::Multiple | KDBusService::NoExitOnFailure); - // Add the domains database. - DomainsDatabaseHelper::addDatabase(); + // Add the databases. + DomainsDatabase::addDatabase(); + CookiesDatabase::addDatabase(); // Create the main window. BrowserWindow *browserWindowPointer = new BrowserWindow(); diff --git a/src/uis/AddOrEditCookieDialog.ui b/src/uis/AddOrEditCookieDialog.ui index adeaa4e..3595e74 100644 --- a/src/uis/AddOrEditCookieDialog.ui +++ b/src/uis/AddOrEditCookieDialog.ui @@ -86,6 +86,40 @@ Qt::AlignLeft + + + + + Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date. + + + + + + + + Durable + + + + Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date. + + + + + + + + Qt::RichText + + + + + &nbsp;&nbsp;&nbsp; + + + + @@ -131,13 +165,13 @@ - - Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes. - - Expiration date + + + Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes. + @@ -205,13 +239,13 @@ - - Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks. - - HTTP only + + + Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks. + @@ -243,13 +277,13 @@ - - Only allow the cookie to be transferred across HTTPS (as opposed to HTTP). - - Secure + + + Only allow the cookie to be transferred across HTTPS (as opposed to HTTP). + diff --git a/src/views/BrowserView.cpp b/src/views/BrowserView.cpp index 440c694..591e16a 100644 --- a/src/views/BrowserView.cpp +++ b/src/views/BrowserView.cpp @@ -21,8 +21,9 @@ #include "BrowserView.h" #include "Settings.h" #include "ui_BrowserView.h" +#include "databases/CookiesDatabase.h" +#include "databases/DomainsDatabase.h" #include "filters/MouseEventFilter.h" -#include "helpers/DomainsDatabaseHelper.h" #include "helpers/SearchEngineHelper.h" #include "helpers/UserAgentHelper.h" #include "interceptors/UrlRequestInterceptor.h" @@ -94,6 +95,13 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent) 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 *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(); @@ -152,7 +160,8 @@ BrowserView::~BrowserView() webEnginePagePointer->deleteLater(); } -void BrowserView::addCookieToStore(QNetworkCookie &cookie) const +// 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; @@ -201,7 +210,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. @@ -210,10 +219,10 @@ 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()) { // Set the default JavaScript status. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled()); @@ -221,7 +230,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Disable JavaScript. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false); @@ -229,7 +238,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Enable JavaScript. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true); @@ -238,10 +247,10 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Set the local storage status. - switch (domainRecord.field(DomainsDatabaseHelper::LOCAL_STORAGE).value().toInt()) + switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt()) { // Set the default local storage status. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled(); @@ -249,7 +258,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Disable local storage. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { currentPrivacyWebEnginePointer->localStorageEnabled = false; @@ -257,7 +266,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Enable local storage. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { currentPrivacyWebEnginePointer->localStorageEnabled = true; @@ -266,10 +275,10 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Set the DOM storage status. - switch (domainRecord.field(DomainsDatabaseHelper::DOM_STORAGE).value().toInt()) + switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt()) { // Set the default DOM storage status. - case (DomainsDatabaseHelper::SYSTEM_DEFAULT): + case (DomainsDatabase::SYSTEM_DEFAULT): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled()); @@ -277,7 +286,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Disable DOM storage. - case (DomainsDatabaseHelper::DISABLED): + case (DomainsDatabase::DISABLED): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false); @@ -285,7 +294,7 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload } // Enable DOM storage. - case (DomainsDatabaseHelper::ENABLED): + case (DomainsDatabase::ENABLED): { webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); @@ -294,13 +303,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 { @@ -312,7 +321,7 @@ 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. { diff --git a/src/views/BrowserView.h b/src/views/BrowserView.h index 859a93f..9396632 100644 --- a/src/views/BrowserView.h +++ b/src/views/BrowserView.h @@ -76,7 +76,7 @@ signals: public Q_SLOTS: // The public slots. - void addCookieToStore(QNetworkCookie &cookie) const; + void addCookieToStore(QNetworkCookie cookie) const; void applyApplicationSettings(); void applyDomainSettingsAndReload(); void applyDomainSettingsWithoutReloading(const QString &hostname); diff --git a/src/windows/BrowserWindow.cpp b/src/windows/BrowserWindow.cpp index 60ddaa4..4a61438 100644 --- a/src/windows/BrowserWindow.cpp +++ b/src/windows/BrowserWindow.cpp @@ -22,6 +22,7 @@ #include "Settings.h" #include "ui_SettingsPrivacy.h" #include "ui_SettingsGeneral.h" +#include "databases/CookiesDatabase.h" #include "dialogs/CookiesDialog.h" #include "dialogs/DomainSettingsDialog.h" #include "helpers/SearchEngineHelper.h" @@ -268,6 +269,10 @@ void BrowserWindow::addCookieToList(const QNetworkCookie &newCookie) const // Update the action text. cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size())); + + // Update the cookie if it is durable and has new data. + if (CookiesDatabase::isUpdate(newCookie)) + CookiesDatabase::updateCookie(newCookie); } void BrowserWindow::addOrEditDomainSettings() const -- 2.43.0