1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 01:22:10 +01:00

Implement per site permissions in database

This includes:
- Cookies
- HTML5 permissions
- WebAttributes
- Panels, tabs, GUI.

BUG: 409496
BUG: 396024
BUG: 451357
CCBUG: 392711

Signed-off-by: Juraj Oravec <jurajoravec@mailo.com>
This commit is contained in:
Juraj Oravec 2022-08-06 16:53:32 +02:00
parent 34bbe6fa76
commit 0dd534d165
Signed by: SGOrava
GPG Key ID: 13660A3F1D9F093B
53 changed files with 3003 additions and 620 deletions

View File

@ -23,6 +23,7 @@ falkon_tests(
webviewtest webviewtest
webtabtest webtabtest
sqldatabasetest sqldatabasetest
sitesettingstest
) )
set(falkon_autotests_SRCS ${CMAKE_SOURCE_DIR}/tests/modeltest/modeltest.cpp) set(falkon_autotests_SRCS ${CMAKE_SOURCE_DIR}/tests/modeltest/modeltest.cpp)

View File

@ -0,0 +1,111 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "sitesettingstest.h"
#include "mainapplication.h"
#include "tabbedwebview.h"
#include "webpage.h"
#include "autotests.h"
#include "tabwidget.h"
void SiteSettingsTest::initTestCase()
{
/* Wait until the initial tab (at index 0) in the window is created */
QTRY_COMPARE(mApp->getWindow()->tabCount(), 1);
}
void SiteSettingsTest::cleanupTestCase()
{
}
void SiteSettingsTest::webAttributeTest()
{
SiteSettingsManager *siteSettings = mApp->siteSettingsManager();
siteSettings->setOption(QWebEngineSettings::AutoLoadImages, QUrl(QSL("https://www.falkon.org/")), SiteSettingsManager::Deny);
siteSettings->setOption(QWebEngineSettings::JavascriptEnabled, QUrl(QSL("https://kde.org/")), SiteSettingsManager::Deny);
siteSettings->setOption(QWebEngineSettings::LocalStorageEnabled, QUrl(QSL("https://store.falkon.org/")), SiteSettingsManager::Deny);
siteSettings->setOption(QWebEngineSettings::PlaybackRequiresUserGesture, QUrl(QSL("https://planet.kde.org/")), SiteSettingsManager::Allow);
WebTab tab;
checkInternalPage(&tab, QUrl(QSL("falkon:start")));
checkExternalPage(&tab, QUrl(QSL("https://www.falkon.org/")));
checkExternalPage(&tab, QUrl(QSL("https://kde.org/")));
checkExternalPage(&tab, QUrl(QSL("https://store.falkon.org/")));
checkInternalPage(&tab, QUrl(QSL("falkon:about")));
checkExternalPage(&tab, QUrl(QSL("https://planet.kde.org/")));
}
bool SiteSettingsTest::checkWebAttributes(WebPage *page, QHash<QWebEngineSettings::WebAttribute, bool> webAttributes)
{
for (auto it = webAttributes.begin(); it != webAttributes.end(); ++it) {
if (page->settings()->testAttribute(it.key()) != it.value()) {
return false;
}
}
return true;
}
void SiteSettingsTest::checkInternalPage(WebTab *tab, QUrl url)
{
QMap<QWebEngineSettings::WebAttribute, bool> internalWebAttributes = {
{QWebEngineSettings::AutoLoadImages, true}
,{QWebEngineSettings::JavascriptEnabled, true}
,{QWebEngineSettings::JavascriptCanOpenWindows, false}
,{QWebEngineSettings::JavascriptCanAccessClipboard, true}
,{QWebEngineSettings::JavascriptCanPaste, false}
,{QWebEngineSettings::AllowWindowActivationFromJavaScript, false}
,{QWebEngineSettings::LocalStorageEnabled, true}
,{QWebEngineSettings::FullScreenSupportEnabled, mApp->webSettings()->testAttribute(QWebEngineSettings::FullScreenSupportEnabled)}
,{QWebEngineSettings::AllowRunningInsecureContent, false}
,{QWebEngineSettings::AllowGeolocationOnInsecureOrigins, false}
,{QWebEngineSettings::PlaybackRequiresUserGesture, mApp->webSettings()->testAttribute(QWebEngineSettings::PlaybackRequiresUserGesture)}
,{QWebEngineSettings::WebRTCPublicInterfacesOnly, false}
};
QSignalSpy spy(tab, SIGNAL(loadingChanged(bool)));
tab->load(url);
QTRY_COMPARE(spy.count(), 3);
auto *page = tab->webView()->page();
for (auto it = internalWebAttributes.begin(); it != internalWebAttributes.end(); ++it) {
QCOMPARE(page->settings()->testAttribute(it.key()), it.value());
}
}
void SiteSettingsTest::checkExternalPage(WebTab *tab, QUrl url)
{
SiteSettingsManager *siteSettings = mApp->siteSettingsManager();
QSignalSpy spy(tab, SIGNAL(loadingChanged(bool)));
tab->load(url);
QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 20000);
auto *page = tab->webView()->page();
QCOMPARE(checkWebAttributes(page, siteSettings->getWebAttributes(url)), true);
}
FALKONTEST_MAIN(SiteSettingsTest)

View File

@ -0,0 +1,47 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef SITESETTINGSTEST_H
#define SITESETTINGSTEST_H
#include "sitesettingsmanager.h"
#include <QObject>
class WebPage;
class WebTab;
class SiteSettingsTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void webAttributeTest();
private:
bool checkWebAttributes(WebPage *page, QHash<QWebEngineSettings::WebAttribute, bool> webAttributes);
void checkInternalPage(WebTab *tab, QUrl url);
void checkExternalPage(WebTab *tab, QUrl url);
};
#endif // SITESETTINGSTEST_H

View File

@ -149,7 +149,9 @@ set(SRCS ${SRCS}
other/licenseviewer.cpp other/licenseviewer.cpp
other/qzsettings.cpp other/qzsettings.cpp
other/siteinfo.cpp other/siteinfo.cpp
other/siteinfopermissionitem.cpp
other/siteinfowidget.cpp other/siteinfowidget.cpp
other/sitesettingsmanager.cpp
other/statusbar.cpp other/statusbar.cpp
other/updater.cpp other/updater.cpp
other/useragentmanager.cpp other/useragentmanager.cpp
@ -208,6 +210,9 @@ set(SRCS ${SRCS}
preferences/pluginsmanager.cpp preferences/pluginsmanager.cpp
preferences/preferences.cpp preferences/preferences.cpp
preferences/schememanager.cpp preferences/schememanager.cpp
preferences/sitesettingsattributesitem.cpp
preferences/sitesettingsbrowsedialog.cpp
preferences/sitesettingshtml5item.cpp
preferences/thememanager.cpp preferences/thememanager.cpp
preferences/useragentdialog.cpp preferences/useragentdialog.cpp
session/recoveryjsobject.cpp session/recoveryjsobject.cpp
@ -242,7 +247,6 @@ set(SRCS ${SRCS}
tools/focusselectlineedit.cpp tools/focusselectlineedit.cpp
tools/headerview.cpp tools/headerview.cpp
tools/horizontallistwidget.cpp tools/horizontallistwidget.cpp
tools/html5permissions/html5permissionsdialog.cpp
tools/html5permissions/html5permissionsmanager.cpp tools/html5permissions/html5permissionsmanager.cpp
tools/html5permissions/html5permissionsnotification.cpp tools/html5permissions/html5permissionsnotification.cpp
tools/iconprovider.cpp tools/iconprovider.cpp
@ -379,7 +383,9 @@ set(SRCS ${SRCS}
other/licenseviewer.h other/licenseviewer.h
other/qzsettings.h other/qzsettings.h
other/siteinfo.h other/siteinfo.h
other/siteinfopermissionitem.h
other/siteinfowidget.h other/siteinfowidget.h
other/sitesettingsmanager.h
other/statusbar.h other/statusbar.h
other/updater.h other/updater.h
other/useragentmanager.h other/useragentmanager.h
@ -438,6 +444,9 @@ set(SRCS ${SRCS}
preferences/pluginsmanager.h preferences/pluginsmanager.h
preferences/preferences.h preferences/preferences.h
preferences/schememanager.h preferences/schememanager.h
preferences/sitesettingsattributesitem.h
preferences/sitesettingsbrowsedialog.h
preferences/sitesettingshtml5item.h
preferences/thememanager.h preferences/thememanager.h
preferences/useragentdialog.h preferences/useragentdialog.h
session/recoveryjsobject.h session/recoveryjsobject.h
@ -472,7 +481,6 @@ set(SRCS ${SRCS}
tools/focusselectlineedit.h tools/focusselectlineedit.h
tools/headerview.h tools/headerview.h
tools/horizontallistwidget.h tools/horizontallistwidget.h
tools/html5permissions/html5permissionsdialog.h
tools/html5permissions/html5permissionsmanager.h tools/html5permissions/html5permissionsmanager.h
tools/html5permissions/html5permissionsnotification.h tools/html5permissions/html5permissionsnotification.h
tools/iconprovider.h tools/iconprovider.h
@ -543,6 +551,7 @@ qt_wrap_ui(SRCS
other/iconchooser.ui other/iconchooser.ui
other/protocolhandlerdialog.ui other/protocolhandlerdialog.ui
other/siteinfo.ui other/siteinfo.ui
other/siteinfopermissionitem.ui
other/siteinfowidget.ui other/siteinfowidget.ui
preferences/acceptlanguage.ui preferences/acceptlanguage.ui
preferences/addacceptlanguage.ui preferences/addacceptlanguage.ui
@ -552,6 +561,9 @@ qt_wrap_ui(SRCS
preferences/pluginslist.ui preferences/pluginslist.ui
preferences/preferences.ui preferences/preferences.ui
preferences/schememanager.ui preferences/schememanager.ui
preferences/sitesettingsattributesitem.ui
preferences/sitesettingsbrowsedialog.ui
preferences/sitesettingshtml5item.ui
preferences/thememanager.ui preferences/thememanager.ui
preferences/useragentdialog.ui preferences/useragentdialog.ui
session/sessionmanagerdialog.ui session/sessionmanagerdialog.ui
@ -559,7 +571,6 @@ qt_wrap_ui(SRCS
sidebar/historysidebar.ui sidebar/historysidebar.ui
tools/certificateinfowidget.ui tools/certificateinfowidget.ui
tools/docktitlebarwidget.ui tools/docktitlebarwidget.ui
tools/html5permissions/html5permissionsdialog.ui
tools/html5permissions/html5permissionsnotification.ui tools/html5permissions/html5permissionsnotification.ui
webengine/jsalert.ui webengine/jsalert.ui
webengine/jsconfirm.ui webengine/jsconfirm.ui

View File

@ -42,6 +42,7 @@
#include "searchenginesmanager.h" #include "searchenginesmanager.h"
#include "desktopnotificationsfactory.h" #include "desktopnotificationsfactory.h"
#include "html5permissions/html5permissionsmanager.h" #include "html5permissions/html5permissionsmanager.h"
#include "sitesettingsmanager.h"
#include "scripts.h" #include "scripts.h"
#include "sessionmanager.h" #include "sessionmanager.h"
#include "closedwindowsmanager.h" #include "closedwindowsmanager.h"
@ -105,6 +106,7 @@ MainApplication::MainApplication(int &argc, char** argv)
, m_closedWindowsManager(nullptr) , m_closedWindowsManager(nullptr)
, m_protocolHandlerManager(nullptr) , m_protocolHandlerManager(nullptr)
, m_html5PermissionsManager(nullptr) , m_html5PermissionsManager(nullptr)
, m_siteSettingsManager(nullptr)
, m_desktopNotifications(nullptr) , m_desktopNotifications(nullptr)
, m_webProfile(nullptr) , m_webProfile(nullptr)
, m_autoSaver(nullptr) , m_autoSaver(nullptr)
@ -645,6 +647,14 @@ HTML5PermissionsManager* MainApplication::html5PermissionsManager()
return m_html5PermissionsManager; return m_html5PermissionsManager;
} }
SiteSettingsManager * MainApplication::siteSettingsManager()
{
if (!m_siteSettingsManager) {
m_siteSettingsManager = new SiteSettingsManager(this);
}
return m_siteSettingsManager;
}
DesktopNotificationsFactory* MainApplication::desktopNotifications() DesktopNotificationsFactory* MainApplication::desktopNotifications()
{ {
if (!m_desktopNotifications) { if (!m_desktopNotifications) {
@ -980,6 +990,13 @@ void MainApplication::loadSettings()
webSettings->setAttribute(QWebEngineSettings::PdfViewerEnabled, settings.value(QSL("intPDFViewer"), false).toBool()); webSettings->setAttribute(QWebEngineSettings::PdfViewerEnabled, settings.value(QSL("intPDFViewer"), false).toBool());
webSettings->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, settings.value(QSL("screenCaptureEnabled"), false).toBool()); webSettings->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, settings.value(QSL("screenCaptureEnabled"), false).toBool());
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
webSettings->setAttribute(QWebEngineSettings::ReadingFromCanvasEnabled, settings.value(QSL("readingFromCanvasEnabled"), false).toBool());
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
webSettings->setAttribute(QWebEngineSettings::ForceDarkMode, settings.value(QSL("forceDarkMode"), false).toBool());
#endif
webSettings->setDefaultTextEncoding(settings.value(QSL("DefaultEncoding"), webSettings->defaultTextEncoding()).toString()); webSettings->setDefaultTextEncoding(settings.value(QSL("DefaultEncoding"), webSettings->defaultTextEncoding()).toString());
setWheelScrollLines(settings.value(QSL("wheelScrollLines"), wheelScrollLines()).toInt()); setWheelScrollLines(settings.value(QSL("wheelScrollLines"), wheelScrollLines()).toInt());

View File

@ -53,6 +53,7 @@ class ProxyStyle;
class SessionManager; class SessionManager;
class ClosedWindowsManager; class ClosedWindowsManager;
class ProtocolHandlerManager; class ProtocolHandlerManager;
class SiteSettingsManager;
class FALKON_EXPORT MainApplication : public QtSingleApplication class FALKON_EXPORT MainApplication : public QtSingleApplication
{ {
@ -111,6 +112,7 @@ public:
ClosedWindowsManager* closedWindowsManager(); ClosedWindowsManager* closedWindowsManager();
ProtocolHandlerManager *protocolHandlerManager(); ProtocolHandlerManager *protocolHandlerManager();
HTML5PermissionsManager* html5PermissionsManager(); HTML5PermissionsManager* html5PermissionsManager();
SiteSettingsManager* siteSettingsManager();
DesktopNotificationsFactory* desktopNotifications(); DesktopNotificationsFactory* desktopNotifications();
QWebEngineProfile* webProfile() const; QWebEngineProfile* webProfile() const;
QWebEngineSettings *webSettings() const; QWebEngineSettings *webSettings() const;
@ -188,6 +190,7 @@ private:
ClosedWindowsManager* m_closedWindowsManager; ClosedWindowsManager* m_closedWindowsManager;
ProtocolHandlerManager *m_protocolHandlerManager; ProtocolHandlerManager *m_protocolHandlerManager;
HTML5PermissionsManager* m_html5PermissionsManager; HTML5PermissionsManager* m_html5PermissionsManager;
SiteSettingsManager* m_siteSettingsManager;
DesktopNotificationsFactory* m_desktopNotifications; DesktopNotificationsFactory* m_desktopNotifications;
QWebEngineProfile* m_webProfile; QWebEngineProfile* m_webProfile;

View File

@ -21,6 +21,8 @@
#include "updater.h" #include "updater.h"
#include "qztools.h" #include "qztools.h"
#include "sqldatabase.h" #include "sqldatabase.h"
#include "sitesettingsmanager.h"
#include "settings.h"
#include <QDir> #include <QDir>
#include <QSqlError> #include <QSqlError>
@ -29,6 +31,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QStandardPaths>
#include <QWebEnginePage>
#include <iostream> #include <iostream>
@ -89,6 +92,7 @@ void ProfileManager::initCurrentProfile(const QString &profileName)
updateCurrentProfile(); updateCurrentProfile();
connectDatabase(); connectDatabase();
updateDatabase();
} }
int ProfileManager::createProfile(const QString &profileName) int ProfileManager::createProfile(const QString &profileName)
@ -166,10 +170,10 @@ void ProfileManager::updateCurrentProfile()
// If file exists, just update the profile to current version // If file exists, just update the profile to current version
if (versionFile.exists()) { if (versionFile.exists()) {
versionFile.open(QFile::ReadOnly); versionFile.open(QFile::ReadOnly);
QString profileVersion = QString::fromUtf8(versionFile.readAll()); profileVersion = QString::fromUtf8(versionFile.readAll()).trimmed();
versionFile.close(); versionFile.close();
updateProfile(QString::fromLatin1(Qz::VERSION), profileVersion.trimmed()); updateProfile(QString::fromLatin1(Qz::VERSION), profileVersion);
} }
else { else {
copyDataToProfile(); copyDataToProfile();
@ -311,3 +315,176 @@ void ProfileManager::connectDatabase()
SqlDatabase::instance()->setDatabase(db); SqlDatabase::instance()->setDatabase(db);
} }
void ProfileManager::updateDatabase()
{
if (QString::fromLatin1(Qz::VERSION) == profileVersion) {
return;
}
Updater::Version prof(profileVersion);
/* Profile is from newer version than running application */
if (prof > Updater::Version(QString::fromLatin1(Qz::VERSION))) {
// Ignore
return;
}
/* Do not try to update database of too old profile */
if (prof < Updater::Version(QStringLiteral("1.9.0"))) {
std::cout << "Falkon: Using profile from QupZilla " << qPrintable(profileVersion) << " is not supported!" << std::endl;
return;
}
/* Update in 24.08.00 */
if (prof < Updater::Version(QStringLiteral("24.07.70"))) {
std::cout << "Falkon: Updating database to version " << qPrintable(QString::fromLatin1(Qz::VERSION)) << std::endl;
SqlDatabase::instance()->database().transaction();
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(QStringLiteral(
"CREATE TABLE IF NOT EXISTS site_settings ("
"id INTEGER PRIMARY KEY,"
"server TEXT NOT NULL,"
"zoom_level INTEGER DEFAULT -1,"
"allow_cookies INTEGER DEFAULT 0,"
"wa_autoload_images INTEGER DEFAULT 0,"
"wa_js_enabled INTEGER DEFAULT 0,"
"wa_js_open_windows INTEGER DEFAULT 0,"
"wa_js_access_clipboard INTEGER DEFAULT 0,"
"wa_js_can_paste INTEGER DEFAULT 0,"
"wa_js_window_activation INTEGER DEFAULT 0,"
"wa_local_storage INTEGER DEFAULT 0,"
"wa_fullscreen_support INTEGER DEFAULT 0,"
"wa_run_insecure_content INTEGER DEFAULT 0,"
"wa_playback_needs_gesture INTEGER DEFAULT 0,"
"wa_reading_from_canvas INTEGER DEFAULT 0,"
"wa_force_dark_mode INTEGER DEFAULT 0,"
"f_notifications INTEGER DEFAULT 0,"
"f_geolocation INTEGER DEFAULT 0,"
"f_media_audio_capture INTEGER DEFAULT 0,"
"f_media_video_capture INTEGER DEFAULT 0,"
"f_media_audio_video_capture INTEGER DEFAULT 0,"
"f_mouse_lock INTEGER DEFAULT 0,"
"f_desktop_video_capture INTEGER DEFAULT 0,"
"f_desktop_audio_video_capture INTEGER DEFAULT 0"
");"
));
if (!query.exec()) {
qCritical() << "Error while creating table 'site_settings' in database: " << query.lastError().text();
qFatal("ProfileManager::updateDatabase Unable to create table 'site_settings' in the database!");
}
query.prepare(QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS site_settings_server_uniqueindex ON site_settings (server);"
));
if (!query.exec()) {
qFatal() << "Error while creating unique index for table 'site_settings': " << query.lastError().text();
}
const QHash<QWebEnginePage::Feature, QString> html5SettingPairs = {
{QWebEnginePage::Notifications, QSL("Notifications")},
{QWebEnginePage::Geolocation, QSL("Geolocation")},
{QWebEnginePage::MediaAudioCapture, QSL("MediaAudioCapture")},
{QWebEnginePage::MediaVideoCapture, QSL("MediaVideoCapture")},
{QWebEnginePage::MediaAudioVideoCapture, QSL("MediaAudioVideoCapture")},
{QWebEnginePage::MouseLock, QSL("MouseLock")},
{QWebEnginePage::DesktopVideoCapture, QSL("DesktopVideoCapture")},
{QWebEnginePage::DesktopAudioVideoCapture,QSL("DesktopAudioVideoCapture")}
};
QHash<QString, SiteSettingsManager::SiteSettings> siteSettings;
Settings settings;
/* HTML5 permissions */
settings.beginGroup(QSL("HTML5Notifications"));
auto loadHtml5Settings = [&](const QString &suflix, const SiteSettingsManager::Permission permission) {
for (auto [feature, settingName] : html5SettingPairs.asKeyValueRange()) {
auto const serverList = settings.value(settingName + suflix, QStringList()).toStringList();
for (const auto &server : serverList) {
if (!siteSettings.contains(server)) {
siteSettings[server] = SiteSettingsManager::SiteSettings();
for (auto [f, nameUnused] : html5SettingPairs.asKeyValueRange()) {
siteSettings[server].features[f] = SiteSettingsManager::Default;
}
}
siteSettings[server].server = server;
siteSettings[server].features[feature] = permission;
}
}
};
loadHtml5Settings(QSL("Granted"), SiteSettingsManager::Allow);
loadHtml5Settings(QSL("Denied"), SiteSettingsManager::Deny);
settings.endGroup();
/* Cookies white/black lists */
settings.beginGroup(QSL("Cookie-Settings"));
auto loadCookiesSettings = [&](const QString &listName, const SiteSettingsManager::Permission permission) {
auto const serverList = settings.value(listName, QStringList()).toStringList();
for (const auto &server : serverList) {
if (!siteSettings.contains(server)) {
siteSettings[server] = SiteSettingsManager::SiteSettings();
}
siteSettings[server].server = server;
siteSettings[server].AllowCookies = permission;
}
};
loadCookiesSettings(QSL("whitelist"), SiteSettingsManager::Allow);
loadCookiesSettings(QSL("blacklist"), SiteSettingsManager::Deny);
settings.endGroup();
/* Insert SQL for SiteSettings */
query.prepare(QSL(
"INSERT INTO site_settings ("
"server,"
"allow_cookies,"
"f_notifications,"
"f_geolocation,"
"f_media_audio_capture,"
"f_media_video_capture,"
"f_media_audio_video_capture,"
"f_mouse_lock,"
"f_desktop_video_capture,"
"f_desktop_audio_video_capture"
")"
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
));
for (const auto &siteSetting : std::as_const(siteSettings)) {
query.bindValue(0, siteSetting.server);
query.bindValue(1, siteSetting.AllowCookies);
query.bindValue(2, siteSetting.features[QWebEnginePage::Notifications]);
query.bindValue(3, siteSetting.features[QWebEnginePage::Geolocation]);
query.bindValue(4, siteSetting.features[QWebEnginePage::MediaAudioCapture]);
query.bindValue(5, siteSetting.features[QWebEnginePage::MediaVideoCapture]);
query.bindValue(6, siteSetting.features[QWebEnginePage::MediaAudioVideoCapture]);
query.bindValue(7, siteSetting.features[QWebEnginePage::MouseLock]);
query.bindValue(8, siteSetting.features[QWebEnginePage::DesktopVideoCapture]);
query.bindValue(9, siteSetting.features[QWebEnginePage::DesktopAudioVideoCapture]);
query.exec();
}
if (!SqlDatabase::instance()->database().commit()) {
SqlDatabase::instance()->database().rollback();
qFatal() << "Unable to update database.";
}
}
}

View File

@ -52,8 +52,11 @@ private:
void updateProfile(const QString &current, const QString &profile); void updateProfile(const QString &current, const QString &profile);
void copyDataToProfile(); void copyDataToProfile();
void migrateFromQupZilla(); void migrateFromQupZilla();
void updateDatabase();
void connectDatabase(); void connectDatabase();
QString profileVersion;
}; };
#endif // PROFILEMANAGER_H #endif // PROFILEMANAGER_H

View File

@ -21,6 +21,8 @@
#include "autosaver.h" #include "autosaver.h"
#include "settings.h" #include "settings.h"
#include "qztools.h" #include "qztools.h"
#include "sitesettingsmanager.h"
#include "sqldatabase.h"
#include <QNetworkCookie> #include <QNetworkCookie>
#include <QWebEngineProfile> #include <QWebEngineProfile>
@ -54,8 +56,6 @@ void CookieJar::loadSettings()
m_allowCookies = settings.value(QSL("allowCookies"), true).toBool(); m_allowCookies = settings.value(QSL("allowCookies"), true).toBool();
m_filterThirdParty = settings.value(QSL("filterThirdPartyCookies"), false).toBool(); m_filterThirdParty = settings.value(QSL("filterThirdPartyCookies"), false).toBool();
m_filterTrackingCookie = settings.value(QSL("filterTrackingCookie"), false).toBool(); m_filterTrackingCookie = settings.value(QSL("filterTrackingCookie"), false).toBool();
m_whitelist = settings.value(QSL("whitelist"), QStringList()).toStringList();
m_blacklist = settings.value(QSL("blacklist"), QStringList()).toStringList();
settings.endGroup(); settings.endGroup();
} }
@ -76,13 +76,28 @@ QVector<QNetworkCookie> CookieJar::getAllCookies() const
void CookieJar::deleteAllCookies(bool deleteAll) void CookieJar::deleteAllCookies(bool deleteAll)
{ {
if (deleteAll || m_whitelist.isEmpty()) { QStringList whitelist;
QSqlDatabase db = SqlDatabase::instance()->database();
QString sqlColumn = mApp->siteSettingsManager()->optionToSqlColumn(SiteSettingsManager::poAllowCookies);
QString sqlTable = mApp->siteSettingsManager()->sqlTable();
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(QSL("SELECT server FROM %1 WHERE %2=?").arg(sqlTable, sqlColumn));
query.addBindValue(SiteSettingsManager::Allow);
query.exec();
while (query.next()) {
QString server = query.value(0).toString();
whitelist.append(server);
}
if (deleteAll || whitelist.isEmpty()) {
m_client->deleteAllCookies(); m_client->deleteAllCookies();
return; return;
} }
for (const QNetworkCookie &cookie : std::as_const(m_cookies)) { for (const QNetworkCookie &cookie : std::as_const(m_cookies)) {
if (!listMatchesDomain(m_whitelist, cookie.domain())) { if (!listMatchesDomain(whitelist, cookie.domain())) {
m_client->deleteCookie(cookie); m_client->deleteCookie(cookie);
} }
} }
@ -134,24 +149,23 @@ void CookieJar::slotCookieRemoved(const QNetworkCookie &cookie)
bool CookieJar::cookieFilter(const QWebEngineCookieStore::FilterRequest &request) const bool CookieJar::cookieFilter(const QWebEngineCookieStore::FilterRequest &request) const
{ {
if (!m_allowCookies) { auto result = mApp->siteSettingsManager()->getPermission(SiteSettingsManager::poAllowCookies, request.origin);
bool result = listMatchesDomain(m_whitelist, request.origin.host()); if (result == SiteSettingsManager::Default) {
if (!result) { result = mApp->siteSettingsManager()->getDefaultPermission(SiteSettingsManager::poAllowCookies);
#ifdef COOKIE_DEBUG
qDebug() << "not in whitelist" << request.origin;
#endif
return false;
}
} }
if (m_allowCookies) { if (!m_allowCookies && (result != SiteSettingsManager::Allow)) {
bool result = listMatchesDomain(m_blacklist, request.origin.host());
if (result) {
#ifdef COOKIE_DEBUG #ifdef COOKIE_DEBUG
qDebug() << "found in blacklist" << request.origin.host(); qDebug() << "Cookies not allowed" << request.origin;
#endif #endif
return false; return false;
} }
if (m_allowCookies && (result == SiteSettingsManager::Deny)) {
#ifdef COOKIE_DEBUG
qDebug() << "Cookies denied" << request.origin;
#endif
return false;
} }
if (m_filterThirdParty && request.thirdParty) { if (m_filterThirdParty && request.thirdParty) {
@ -168,24 +182,23 @@ bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie
{ {
Q_UNUSED(domain) Q_UNUSED(domain)
if (!m_allowCookies) { auto result = mApp->siteSettingsManager()->getPermission(SiteSettingsManager::poAllowCookies, cookieDomain);
bool result = listMatchesDomain(m_whitelist, cookieDomain); if (result == SiteSettingsManager::Default) {
if (!result) { result = mApp->siteSettingsManager()->getDefaultPermission(SiteSettingsManager::poAllowCookies);
#ifdef COOKIE_DEBUG
qDebug() << "not in whitelist" << cookie;
#endif
return true;
}
} }
if (m_allowCookies) { if (!m_allowCookies && (result != SiteSettingsManager::Allow)) {
bool result = listMatchesDomain(m_blacklist, cookieDomain);
if (result) {
#ifdef COOKIE_DEBUG #ifdef COOKIE_DEBUG
qDebug() << "found in blacklist" << cookie; qDebug() << "Cookies not allowed" << cookie;
#endif #endif
return true; return false;
} }
if (m_allowCookies && (result == SiteSettingsManager::Deny)) {
#ifdef COOKIE_DEBUG
qDebug() << "Cookies denied" << cookie;
#endif
return false;
} }
#ifdef QTWEBENGINE_DISABLED #ifdef QTWEBENGINE_DISABLED

View File

@ -65,9 +65,6 @@ private:
bool m_filterTrackingCookie; bool m_filterTrackingCookie;
bool m_filterThirdParty; bool m_filterThirdParty;
QStringList m_whitelist;
QStringList m_blacklist;
QWebEngineCookieStore *m_client; QWebEngineCookieStore *m_client;
QVector<QNetworkCookie> m_cookies; QVector<QNetworkCookie> m_cookies;
}; };

View File

@ -23,6 +23,8 @@
#include "qztools.h" #include "qztools.h"
#include "settings.h" #include "settings.h"
#include "iconprovider.h" #include "iconprovider.h"
#include "sqldatabase.h"
#include "sitesettingsmanager.h"
#include <QNetworkCookie> #include <QNetworkCookie>
#include <QMessageBox> #include <QMessageBox>
@ -71,8 +73,6 @@ CookieManager::CookieManager(QWidget *parent)
ui->filter3rdParty->setChecked(settings.value(QSL("filterThirdPartyCookies"), false).toBool()); ui->filter3rdParty->setChecked(settings.value(QSL("filterThirdPartyCookies"), false).toBool());
ui->filterTracking->setChecked(settings.value(QSL("filterTrackingCookie"), false).toBool()); ui->filterTracking->setChecked(settings.value(QSL("filterTrackingCookie"), false).toBool());
ui->deleteCookiesOnClose->setChecked(settings.value(QSL("deleteCookiesOnClose"), false).toBool()); ui->deleteCookiesOnClose->setChecked(settings.value(QSL("deleteCookiesOnClose"), false).toBool());
ui->whiteList->addItems(settings.value(QSL("whitelist"), QStringList()).toStringList());
ui->blackList->addItems(settings.value(QSL("blacklist"), QStringList()).toStringList());
settings.endGroup(); settings.endGroup();
ui->search->setPlaceholderText(tr("Search")); ui->search->setPlaceholderText(tr("Search"));
@ -81,6 +81,8 @@ CookieManager::CookieManager(QWidget *parent)
ui->cookieTree->header()->setDefaultSectionSize(220); ui->cookieTree->header()->setDefaultSectionSize(220);
ui->cookieTree->setFocus(); ui->cookieTree->setFocus();
initWhiteAndBlacklist();
ui->whiteList->sortItems(Qt::AscendingOrder); ui->whiteList->sortItems(Qt::AscendingOrder);
ui->blackList->sortItems(Qt::AscendingOrder); ui->blackList->sortItems(Qt::AscendingOrder);
@ -100,6 +102,32 @@ CookieManager::CookieManager(QWidget *parent)
QzTools::setWmClass(QSL("Cookies"), this); QzTools::setWmClass(QSL("Cookies"), this);
} }
void CookieManager::initWhiteAndBlacklist()
{
QSqlDatabase db = SqlDatabase::instance()->database();
QString sqlColumn = mApp->siteSettingsManager()->optionToSqlColumn(SiteSettingsManager::poAllowCookies);
QString sqlTable = mApp->siteSettingsManager()->sqlTable();
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(QSL("SELECT server FROM %1 WHERE %2=?").arg(sqlTable, sqlColumn));
query.addBindValue(SiteSettingsManager::Allow);
query.exec();
while (query.next()) {
QString server = query.value(0).toString();
ui->whiteList->addItem(server);
}
query.addBindValue(SiteSettingsManager::Deny);
query.exec();
while (query.next()) {
QString server = query.value(0).toString();
ui->blackList->addItem(server);
}
}
void CookieManager::removeAll() void CookieManager::removeAll()
{ {
QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Confirmation"), QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Confirmation"),
@ -196,11 +224,15 @@ void CookieManager::addWhitelist()
if (ui->whiteList->findItems(server, Qt::MatchFixedString).isEmpty()) { if (ui->whiteList->findItems(server, Qt::MatchFixedString).isEmpty()) {
ui->whiteList->addItem(server); ui->whiteList->addItem(server);
m_listModifications[server] = SiteSettingsManager::Allow;
} }
} }
void CookieManager::removeWhitelist() void CookieManager::removeWhitelist()
{ {
QString server = ui->whiteList->currentItem()->text();
m_listModifications[server] = SiteSettingsManager::Default;
delete ui->whiteList->currentItem(); delete ui->whiteList->currentItem();
} }
@ -223,6 +255,7 @@ void CookieManager::addBlacklist(const QString &server)
if (ui->blackList->findItems(server, Qt::MatchFixedString).isEmpty()) { if (ui->blackList->findItems(server, Qt::MatchFixedString).isEmpty()) {
ui->blackList->addItem(server); ui->blackList->addItem(server);
m_listModifications[server] = SiteSettingsManager::Deny;
} }
} }
@ -248,6 +281,9 @@ QTreeWidgetItem *CookieManager::cookieItem(const QNetworkCookie &cookie) const
void CookieManager::removeBlacklist() void CookieManager::removeBlacklist()
{ {
QString server = ui->blackList->currentItem()->text();
m_listModifications[server] = SiteSettingsManager::Default;
delete ui->blackList->currentItem(); delete ui->blackList->currentItem();
} }
@ -328,15 +364,11 @@ void CookieManager::removeCookie(const QNetworkCookie &cookie)
void CookieManager::closeEvent(QCloseEvent* e) void CookieManager::closeEvent(QCloseEvent* e)
{ {
QStringList whitelist; QUrl url;
QStringList blacklist;
for (int i = 0; i < ui->whiteList->count(); ++i) { for (QHash<QString, int>::iterator it = m_listModifications.begin(); it != m_listModifications.end(); ++it) {
whitelist.append(ui->whiteList->item(i)->text()); url.setHost(it.key());
} mApp->siteSettingsManager()->setOption(SiteSettingsManager::poAllowCookies, url, it.value());
for (int i = 0; i < ui->blackList->count(); ++i) {
blacklist.append(ui->blackList->item(i)->text());
} }
Settings settings; Settings settings;
@ -345,8 +377,6 @@ void CookieManager::closeEvent(QCloseEvent* e)
settings.setValue(QSL("filterThirdPartyCookies"), ui->filter3rdParty->isChecked()); settings.setValue(QSL("filterThirdPartyCookies"), ui->filter3rdParty->isChecked());
settings.setValue(QSL("filterTrackingCookie"), ui->filterTracking->isChecked()); settings.setValue(QSL("filterTrackingCookie"), ui->filterTracking->isChecked());
settings.setValue(QSL("deleteCookiesOnClose"), ui->deleteCookiesOnClose->isChecked()); settings.setValue(QSL("deleteCookiesOnClose"), ui->deleteCookiesOnClose->isChecked());
settings.setValue(QSL("whitelist"), whitelist);
settings.setValue(QSL("blacklist"), blacklist);
settings.endGroup(); settings.endGroup();
mApp->cookieJar()->loadSettings(); mApp->cookieJar()->loadSettings();

View File

@ -61,12 +61,15 @@ private:
void closeEvent(QCloseEvent* e) override; void closeEvent(QCloseEvent* e) override;
void keyPressEvent(QKeyEvent* e) override; void keyPressEvent(QKeyEvent* e) override;
void initWhiteAndBlacklist();
void addBlacklist(const QString &server); void addBlacklist(const QString &server);
QString cookieDomain(const QNetworkCookie &cookie) const; QString cookieDomain(const QNetworkCookie &cookie) const;
QTreeWidgetItem *cookieItem(const QNetworkCookie &cookie) const; QTreeWidgetItem *cookieItem(const QNetworkCookie &cookie) const;
Ui::CookieManager* ui; Ui::CookieManager* ui;
QHash<QString, int> m_listModifications;
QHash<QString, QTreeWidgetItem*> m_domainHash; QHash<QString, QTreeWidgetItem*> m_domainHash;
QHash<QTreeWidgetItem*, QNetworkCookie> m_itemHash; QHash<QTreeWidgetItem*, QNetworkCookie> m_itemHash;
}; };

View File

@ -55,4 +55,35 @@ CREATE TABLE icons (
); );
CREATE UNIQUE INDEX icons_urluniqueindex ON icons (url); CREATE UNIQUE INDEX icons_urluniqueindex ON icons (url);
CREATE TABLE site_settings (
id INTEGER PRIMARY KEY,
server TEXT NOT NULL,
zoom_level INTEGER DEFAULT -1,
allow_cookies INTEGER DEFAULT 0,
wa_autoload_images INTEGER DEFAULT 0,
wa_js_enabled INTEGER DEFAULT 0,
wa_js_open_windows INTEGER DEFAULT 0,
wa_js_access_clipboard INTEGER DEFAULT 0,
wa_js_can_paste INTEGER DEFAULT 0,
wa_js_window_activation INTEGER DEFAULT 0,
wa_local_storage INTEGER DEFAULT 0,
wa_fullscreen_support INTEGER DEFAULT 0,
wa_run_insecure_content INTEGER DEFAULT 0,
wa_playback_needs_gesture INTEGER DEFAULT 0,
wa_reading_from_canvas INTEGER DEFAULT 0,
wa_force_dark_mode INTEGER DEFAULT 0,
f_notifications INTEGER DEFAULT 0,
f_geolocation INTEGER DEFAULT 0,
f_media_audio_capture INTEGER DEFAULT 0,
f_media_video_capture INTEGER DEFAULT 0,
f_media_audio_video_capture INTEGER DEFAULT 0,
f_mouse_lock INTEGER DEFAULT 0,
f_desktop_video_capture INTEGER DEFAULT 0,
f_desktop_audio_video_capture INTEGER DEFAULT 0
);
CREATE UNIQUE INDEX site_settings_serveruniqueindex ON site_settings (server);
-- Data -- Data

View File

@ -37,6 +37,7 @@
#include <QTimer> #include <QTimer>
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <QShortcut> #include <QShortcut>
#include <QListWidgetItem>
SiteInfo::SiteInfo(WebView *view) SiteInfo::SiteInfo(WebView *view)
: QDialog(view) : QDialog(view)
@ -58,6 +59,7 @@ SiteInfo::SiteInfo(WebView *view)
ui->listWidget->item(0)->setIcon(QIcon::fromTheme(QSL("document-properties"), QIcon(QSL(":/icons/preferences/document-properties.png")))); ui->listWidget->item(0)->setIcon(QIcon::fromTheme(QSL("document-properties"), QIcon(QSL(":/icons/preferences/document-properties.png"))));
ui->listWidget->item(1)->setIcon(QIcon::fromTheme(QSL("applications-graphics"), QIcon(QSL(":/icons/preferences/applications-graphics.png")))); ui->listWidget->item(1)->setIcon(QIcon::fromTheme(QSL("applications-graphics"), QIcon(QSL(":/icons/preferences/applications-graphics.png"))));
ui->listWidget->item(2)->setIcon(QIcon(QStringLiteral(":/icons/preferences/privacy.svg")));
ui->listWidget->item(0)->setSelected(true); ui->listWidget->item(0)->setSelected(true);
// General // General
@ -122,11 +124,15 @@ SiteInfo::SiteInfo(WebView *view)
} }
}); });
/* Permissions */
addSiteSettings();
connect(ui->saveButton, SIGNAL(clicked(QAbstractButton*)), this, SLOT(saveImage())); connect(ui->saveButton, SIGNAL(clicked(QAbstractButton*)), this, SLOT(saveImage()));
connect(ui->listWidget, SIGNAL(currentRowChanged(int)), ui->stackedWidget, SLOT(setCurrentIndex(int))); connect(ui->listWidget, SIGNAL(currentRowChanged(int)), ui->stackedWidget, SLOT(setCurrentIndex(int)));
connect(ui->treeImages, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(showImagePreview(QTreeWidgetItem*))); connect(ui->treeImages, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(showImagePreview(QTreeWidgetItem*)));
connect(ui->treeImages, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(imagesCustomContextMenuRequested(QPoint))); connect(ui->treeImages, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(imagesCustomContextMenuRequested(QPoint)));
connect(ui->treeTags, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(tagsCustomContextMenuRequested(QPoint))); connect(ui->treeTags, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(tagsCustomContextMenuRequested(QPoint)));
connect(this, &QDialog::accepted, this, &SiteInfo::saveSiteSettings);
auto *shortcutTagsCopyAll = new QShortcut(QKeySequence(QSL("Ctrl+C")), ui->treeTags); auto *shortcutTagsCopyAll = new QShortcut(QKeySequence(QSL("Ctrl+C")), ui->treeTags);
shortcutTagsCopyAll->setContext(Qt::WidgetShortcut); shortcutTagsCopyAll->setContext(Qt::WidgetShortcut);
@ -323,3 +329,57 @@ SiteInfo::~SiteInfo()
delete ui; delete ui;
delete m_certWidget; delete m_certWidget;
} }
SiteInfoPermissionItem* SiteInfo::addPermissionOption(SiteSettingsManager::Permission perm)
{
auto* listItem = new QListWidgetItem(ui->listPermissions);
auto* optionItem = new SiteInfoPermissionItem(perm, this);
ui->listPermissions->setItemWidget(listItem, optionItem);
listItem->setSizeHint(optionItem->sizeHint());
return optionItem;
}
void SiteInfo::addSiteSettings()
{
auto siteSettings = mApp->siteSettingsManager()->getSiteSettings(m_baseUrl);
const auto supportedAttribute = mApp->siteSettingsManager()->getSupportedAttribute();
for (const auto &attribute : supportedAttribute) {
SiteInfoPermissionItem *item = addPermissionOption(siteSettings.attributes[attribute]);
item->setAttribute(attribute);
}
const auto supportedFeatures = mApp->siteSettingsManager()->getSupportedFeatures();
for (const auto &feature : supportedFeatures) {
SiteInfoPermissionItem *item = addPermissionOption(siteSettings.features[feature]);
item->setFeature(feature);
}
SiteInfoPermissionItem *item = addPermissionOption(siteSettings.AllowCookies);
item->setOption(SiteSettingsManager::poAllowCookies);
}
void SiteInfo::saveSiteSettings()
{
SiteSettings siteSettings;
int index = 0;
auto supportedAttribute = mApp->siteSettingsManager()->getSupportedAttribute();
auto supportedFeatures = mApp->siteSettingsManager()->getSupportedFeatures();
for (int i = 0; i < supportedAttribute.size(); ++i, ++index) {
auto* item = static_cast<SiteInfoPermissionItem*>(ui->listPermissions->itemWidget(ui->listPermissions->item(index)));
siteSettings.attributes[supportedAttribute[i]] = item->permission();
}
for (int i = 0; i < supportedFeatures.size(); ++i, ++index) {
auto* item = static_cast<SiteInfoPermissionItem*>(ui->listPermissions->itemWidget(ui->listPermissions->item(index)));
siteSettings.features[supportedFeatures[i]] = item->permission();
}
auto* item = static_cast<SiteInfoPermissionItem*>(ui->listPermissions->itemWidget(ui->listPermissions->item(index++)));
siteSettings.AllowCookies = item->permission();
siteSettings.ZoomLevel = -1;
siteSettings.server = m_baseUrl.host();
if (!(siteSettings == mApp->siteSettingsManager()->getSiteSettings(m_baseUrl))) {
mApp->siteSettingsManager()->setSiteSettings(siteSettings);
}
}

View File

@ -19,6 +19,8 @@
#define SITEINFO_H #define SITEINFO_H
#include "qzcommon.h" #include "qzcommon.h"
#include "sitesettingsmanager.h"
#include "siteinfopermissionitem.h"
#include <QUrl> #include <QUrl>
#include <QDialog> #include <QDialog>
@ -51,11 +53,15 @@ private Q_SLOTS:
void tagsCustomContextMenuRequested(const QPoint &p); void tagsCustomContextMenuRequested(const QPoint &p);
void copySelectedItems(const QTreeWidget* treeWidget, const bool both); void copySelectedItems(const QTreeWidget* treeWidget, const bool both);
void saveImage(); void saveImage();
void saveSiteSettings();
private: private:
void showLoadingText(); void showLoadingText();
void showPixmap(QPixmap pixmap); void showPixmap(QPixmap pixmap);
void addSiteSettings();
SiteInfoPermissionItem* addPermissionOption(SiteSettingsManager::Permission perm);
Ui::SiteInfo* ui; Ui::SiteInfo* ui;
CertificateInfoWidget* m_certWidget; CertificateInfoWidget* m_certWidget;
WebView* m_view; WebView* m_view;

View File

@ -20,7 +20,7 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
</item> </item>
@ -52,6 +52,11 @@
<string>Media</string> <string>Media</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>Permissions</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
@ -281,6 +286,20 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QListWidget" name="listPermissions">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -303,7 +322,7 @@
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>SiteInfo</receiver> <receiver>SiteInfo</receiver>
<slot>close()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>248</x> <x>248</x>
@ -315,5 +334,21 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SiteInfo</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>294</x>
<y>472</y>
</hint>
<hint type="destinationlabel">
<x>294</x>
<y>245</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

View File

@ -0,0 +1,130 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2022 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "siteinfopermissionitem.h"
#include "ui_siteinfopermissionitem.h"
#include "mainapplication.h"
#include "sitesettingsmanager.h"
SiteInfoPermissionItem::SiteInfoPermissionItem(const SiteSettingsManager::Permission& a_permission, QWidget* parent)
: QWidget(parent)
, m_hasOptionAsk(true)
, m_ui(new Ui::SiteInfoPermissionItem())
{
m_ui->setupUi(this);
setPermission(a_permission);
}
SiteInfoPermissionItem::~SiteInfoPermissionItem() = default;
bool SiteInfoPermissionItem::hasOptionAsk() const
{
return m_hasOptionAsk;
}
void SiteInfoPermissionItem::setHasOptionAsk(bool hasOptionAsk)
{
if (m_hasOptionAsk == hasOptionAsk) {
return;
}
m_hasOptionAsk = hasOptionAsk;
m_ui->radioAsk->setVisible(hasOptionAsk);
}
void SiteInfoPermissionItem::setPermission(const SiteSettingsManager::Permission permission)
{
m_ui->radioAllow->setChecked(false);
m_ui->radioAsk->setChecked(false);
m_ui->radioDeny->setChecked(false);
m_ui->radioDefault->setChecked(false);
switch (permission) {
case SiteSettingsManager::Allow:
m_ui->radioAllow->setChecked(true);
break;
case SiteSettingsManager::Ask:
m_ui->radioAsk->setChecked(true);
break;
case SiteSettingsManager::Deny:
m_ui->radioDeny->setChecked(true);
break;
case SiteSettingsManager::Default:
m_ui->radioDefault->setChecked(true);
break;
default:
qWarning() << "Unknown permission" << permission;
m_ui->radioDefault->setChecked(true);
}
}
SiteSettingsManager::Permission SiteInfoPermissionItem::permission() const
{
if (m_ui->radioAllow->isChecked()) {
return SiteSettingsManager::Allow;
}
else if (m_ui->radioAsk->isChecked()) {
return SiteSettingsManager::Ask;
}
else if (m_ui->radioDeny->isChecked()) {
return SiteSettingsManager::Deny;
}
else if (m_ui->radioDefault->isChecked()) {
return SiteSettingsManager::Default;
}
else {
qWarning() << "No permission is selected";
return SiteSettingsManager::Default;
}
}
QString SiteInfoPermissionItem::sqlColumn()
{
return m_sqlColumn;
}
void SiteInfoPermissionItem::setDefaultPermission(SiteSettingsManager::Permission permission)
{
if (permission == SiteSettingsManager::Default) {
permission = SiteSettingsManager::Ask;
}
m_ui->labelDefaultPermission->setText(mApp->siteSettingsManager()->getPermissionName(permission));
}
void SiteInfoPermissionItem::setAttribute(const QWebEngineSettings::WebAttribute &attribute)
{
m_sqlColumn = mApp->siteSettingsManager()->webAttributeToSqlColumn(attribute);
m_ui->label->setText(mApp->siteSettingsManager()->getOptionName(attribute));
setDefaultPermission(mApp->siteSettingsManager()->getDefaultPermission(attribute));
setHasOptionAsk(false);
}
void SiteInfoPermissionItem::setFeature(const QWebEnginePage::Feature& feature)
{
m_sqlColumn = mApp->siteSettingsManager()->featureToSqlColumn(feature);
m_ui->label->setText(mApp->siteSettingsManager()->getOptionName(feature));
setDefaultPermission(mApp->siteSettingsManager()->getDefaultPermission(feature));
}
void SiteInfoPermissionItem::setOption(const SiteSettingsManager::PageOptions& option)
{
m_sqlColumn = mApp->siteSettingsManager()->optionToSqlColumn(option);
m_ui->label->setText(mApp->siteSettingsManager()->getOptionName(option));
setDefaultPermission(mApp->siteSettingsManager()->getDefaultPermission(option));
setHasOptionAsk(false);
}

View File

@ -0,0 +1,64 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2022 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef SITEINFOPERMISSIONITEM_H
#define SITEINFOPERMISSIONITEM_H
#include "sitesettingsmanager.h"
#include <qwidget.h>
#include <QScopedPointer>
namespace Ui
{
class SiteInfoPermissionItem;
}
/**
* @todo write docs
*/
class SiteInfoPermissionItem : public QWidget
{
Q_OBJECT
public:
explicit SiteInfoPermissionItem(const SiteSettingsManager::Permission &a_permission, QWidget* parent = nullptr);
~SiteInfoPermissionItem();
bool hasOptionAsk() const;
SiteSettingsManager::Permission permission() const;
QString sqlColumn();
void setAttribute(const QWebEngineSettings::WebAttribute& attribute);
void setFeature(const QWebEnginePage::Feature &feature);
void setOption(const SiteSettingsManager::PageOptions &option);
void setHasOptionAsk(bool hasAsk);
private:
void setPermission(const SiteSettingsManager::Permission permission);
void setDefaultPermission(SiteSettingsManager::Permission permission);
bool m_hasOptionAsk;
QString m_sqlColumn;
private:
QScopedPointer<Ui::SiteInfoPermissionItem> m_ui;
};
#endif // SITEINFOPERMISSIONITEM_H

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SiteInfoPermissionItem</class>
<widget class="QWidget" name="SiteInfoPermissionItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>66</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioDefault">
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelDefaultPermission">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="radioAsk">
<property name="text">
<string>Ask</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioAllow">
<property name="text">
<string>Allow</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioDeny">
<property name="text">
<string>Deny</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,627 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2022 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "sitesettingsmanager.h"
#include "mainapplication.h"
#include "settings.h"
#include "sqldatabase.h"
#include <QUrl>
#include <QtWebEngineCoreVersion>
const QList<QWebEngineSettings::WebAttribute> supportedAttribute = {
QWebEngineSettings::AutoLoadImages
,QWebEngineSettings::JavascriptEnabled
,QWebEngineSettings::JavascriptCanOpenWindows
,QWebEngineSettings::JavascriptCanAccessClipboard
,QWebEngineSettings::JavascriptCanPaste
,QWebEngineSettings::AllowWindowActivationFromJavaScript
,QWebEngineSettings::LocalStorageEnabled
,QWebEngineSettings::FullScreenSupportEnabled
,QWebEngineSettings::AllowRunningInsecureContent
,QWebEngineSettings::PlaybackRequiresUserGesture
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
,QWebEngineSettings::ReadingFromCanvasEnabled
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
,QWebEngineSettings::ForceDarkMode
#endif
};
const QList<QWebEnginePage::Feature> supportedFeatures = {
QWebEnginePage::Notifications
,QWebEnginePage::Geolocation
,QWebEnginePage::MediaAudioCapture
,QWebEnginePage::MediaVideoCapture
,QWebEnginePage::MediaAudioVideoCapture
,QWebEnginePage::MouseLock
,QWebEnginePage::DesktopVideoCapture
,QWebEnginePage::DesktopAudioVideoCapture
};
SiteSettingsManager::SiteSettingsManager ( QObject* parent )
: QObject(parent)
{
prepareSqls();
loadSettings();
}
SiteSettingsManager::~SiteSettingsManager() = default;
void SiteSettingsManager::loadSettings()
{
Settings settings;
settings.beginGroup(QSL("Site-Settings"));
/* HTML5 Feature */
for (const auto &feature : std::as_const(supportedFeatures)) {
defaultFeatures[feature] = intToPermission(settings.value(featureToSqlColumn(feature), Ask).toInt());
}
settings.endGroup();
}
void SiteSettingsManager::saveSettings()
{
Settings settings;
settings.beginGroup(QSL("Site-Settings"));
for (auto it = defaultFeatures.begin(); it != defaultFeatures.end(); ++it) {
settings.setValue(featureToSqlColumn(it.key()), it.value());
}
settings.endGroup();
}
QHash<QWebEngineSettings::WebAttribute, bool> SiteSettingsManager::getWebAttributes(const QUrl& url)
{
QHash<QWebEngineSettings::WebAttribute, bool> attributes;
QString host = url.host();
if (host.isEmpty()) {
for (int i = 0; i < supportedAttribute.size(); ++i) {
QWebEngineSettings::WebAttribute attribute = supportedAttribute[i];
attributes[attribute] = mApp->webSettings()->testAttribute(attribute);
}
return attributes;
}
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(attributesSql);
query.addBindValue(host);
query.exec();
if (query.next()) {
for (int i = 0; i < query.record().count(); ++i) {
SiteSettingsManager::Permission perm = intToPermission(query.value(i).toInt());
QWebEngineSettings::WebAttribute attribute = supportedAttribute[i];
if (perm == Allow) {
attributes[attribute] = true;
}
else if (perm == Deny) {
attributes[attribute] = false;
}
else {
attributes[attribute] = mApp->webSettings()->testAttribute(attribute);
}
}
}
return attributes;
}
void SiteSettingsManager::setOption(const QString& column, const QUrl& url, const int value)
{
QString host = url.host();
if (column.isEmpty() || host.isEmpty()) {
return;
}
auto job = new SqlQueryJob(QSL("UPDATE %2 SET %1=? WHERE server=?").arg(column, sqlTable()), this);
job->addBindValue(value);
job->addBindValue(host);
connect(job, &SqlQueryJob::finished, this, [=]() {
if (job->numRowsAffected() == 0) {
auto job = new SqlQueryJob(QSL("INSERT INTO %2 (server, %1) VALUES (?,?)").arg(column, sqlTable()), this);
job->addBindValue(host);
job->addBindValue(value);
job->start();
}
});
job->start();
}
void SiteSettingsManager::setOption(const PageOptions option, const QUrl& url, const int value)
{
setOption(optionToSqlColumn(option), url, value);
}
void SiteSettingsManager::setOption(const QWebEnginePage::Feature& feature, const QUrl& url, const SiteSettingsManager::Permission value)
{
setOption(featureToSqlColumn(feature), url, value);
}
void SiteSettingsManager::setOption(const QWebEngineSettings::WebAttribute& attribute, const QUrl& url, const SiteSettingsManager::Permission value)
{
setOption(webAttributeToSqlColumn(attribute), url, value);
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QString& column, const QString& host)
{
if (column.isEmpty()) {
return Deny;
}
if (host.isEmpty()) {
return Default;
}
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(QSL("SELECT %1 FROM %2 WHERE server=?").arg(column, sqlTable()));
query.addBindValue(host);
query.exec();
if (query.next()) {
int allow_option = query.value(column).toInt();
return intToPermission(allow_option);
}
return Default;
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const SiteSettingsManager::PageOptions option, const QString& host)
{
return getPermission(optionToSqlColumn(option), host);
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QWebEnginePage::Feature feature, const QString& host)
{
return getPermission(featureToSqlColumn(feature), host);
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QWebEngineSettings::WebAttribute attribute, const QString& host)
{
return getPermission(webAttributeToSqlColumn(attribute), host);
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QString &column, const QUrl& url)
{
return getPermission(column, url.host());
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const SiteSettingsManager::PageOptions option, const QUrl& url)
{
return getPermission(optionToSqlColumn(option), url.host());
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QWebEnginePage::Feature feature, const QUrl& url)
{
return getPermission(featureToSqlColumn(feature), url.host());
}
SiteSettingsManager::Permission SiteSettingsManager::getPermission(const QWebEngineSettings::WebAttribute attribute, const QUrl& url)
{
return getPermission(webAttributeToSqlColumn(attribute), url.host());
}
SiteSettingsManager::Permission SiteSettingsManager::getDefaultPermission(const SiteSettingsManager::PageOptions option)
{
switch (option) {
case poAllowCookies: {
Settings settings;
settings.beginGroup(QSL("Cookie-Settings"));
auto defaultCookies = settings.value(QSL("allowCookies"), true).toBool() ? Allow : Deny;
settings.endGroup();
return defaultCookies;
}
// so far not implemented
case poZoomLevel:
default:
qWarning() << "Unknown option:" << option;
return Deny;
}
}
SiteSettingsManager::Permission SiteSettingsManager::getDefaultPermission(const QWebEnginePage::Feature feature) const
{
if (!supportedFeatures.contains(feature)) {
qWarning() << "Unknown feature:" << feature;
return Deny;
}
return defaultFeatures[feature];
}
SiteSettingsManager::Permission SiteSettingsManager::getDefaultPermission(const QWebEngineSettings::WebAttribute attribute) const
{
if (!supportedAttribute.contains(attribute)) {
qWarning() << "Unknown attribute:" << attribute;
return Deny;
}
if (mApp->webSettings()->testAttribute(attribute)) {
return Allow;
}
else {
return Deny;
}
}
SiteSettingsManager::Permission SiteSettingsManager::intToPermission(const int permission) const
{
switch (permission) {
case Allow:
return Allow;
case Deny:
return Deny;
case Ask:
return Ask;
default:
return Default;
}
}
QString SiteSettingsManager::getOptionName(const SiteSettingsManager::PageOptions option) const
{
switch (option) {
case poZoomLevel:
return tr("Zoom level");
case poAllowCookies:
return tr("Cookies");
default:
qWarning() << "Unknown option:" << option;
return tr("Unknown");;
}
}
QString SiteSettingsManager::getOptionName(const QWebEnginePage::Feature feature) const
{
switch (feature) {
case QWebEnginePage::Notifications:
return tr("Notifications");
case QWebEnginePage::Geolocation:
return tr("Geolocation");
case QWebEnginePage::MediaAudioCapture:
return tr("Microphone");
case QWebEnginePage::MediaVideoCapture:
return tr("Camera");
case QWebEnginePage::MediaAudioVideoCapture:
return tr("Microphone and Camera");
case QWebEnginePage::MouseLock:
return tr("Hide mouse pointer");
case QWebEnginePage::DesktopVideoCapture:
return tr("Screen capture");
case QWebEnginePage::DesktopAudioVideoCapture:
return tr("Screen capture with audio");
default:
qWarning() << "Unknown feature:" << feature;
return tr("Unknown");
}
}
QString SiteSettingsManager::getOptionName(const QWebEngineSettings::WebAttribute attribute) const
{
switch (attribute) {
case QWebEngineSettings::AutoLoadImages:
return tr("Autoload images");
case QWebEngineSettings::JavascriptEnabled:
return tr("Enable JavaScript");
case QWebEngineSettings::JavascriptCanOpenWindows:
return tr("JavaScript: Open popup windows");
case QWebEngineSettings::JavascriptCanAccessClipboard:
return tr("JavaScript: Access clipboard");
case QWebEngineSettings::JavascriptCanPaste:
return tr("JavaScript: Paste from clipboard");
case QWebEngineSettings::AllowWindowActivationFromJavaScript:
return tr("JavaScript: Activate windows");
case QWebEngineSettings::LocalStorageEnabled:
return tr("Local storage");
case QWebEngineSettings::FullScreenSupportEnabled:
return tr("FullScreen support");
case QWebEngineSettings::AllowRunningInsecureContent:
return tr("Run insecure content");
case QWebEngineSettings::PlaybackRequiresUserGesture:
return tr("Automatic playing of videos");
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
case QWebEngineSettings::ReadingFromCanvasEnabled:
return tr("Allow reading from canvas");
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
case QWebEngineSettings::ForceDarkMode:
return tr("Force dark mode");
#endif
default:
qWarning() << "Unknown attribute:" << attribute;
return tr("Unknown");
}
}
QString SiteSettingsManager::getPermissionName(const SiteSettingsManager::Permission permission) const
{
switch (permission) {
case Allow:
return tr("Allow");
case Ask:
return tr("Ask");
case Deny:
return tr("Deny");
case Default:
return tr("Default");
default:
qWarning() << "Uknown permission:" << permission;
return tr("Unknown");
}
}
QString SiteSettingsManager::optionToSqlColumn(const SiteSettingsManager::PageOptions option) const
{
switch (option) {
case poAllowCookies:
return QSL("allow_cookies");
case poZoomLevel:
return QSL("zoom_level");
default:
qWarning() << "Unknown option:" << option;
return QLatin1String("");
}
}
QString SiteSettingsManager::featureToSqlColumn(const QWebEnginePage::Feature feature) const
{
switch (feature) {
case QWebEnginePage::Notifications:
return QSL("f_notifications");
case QWebEnginePage::Geolocation:
return QSL("f_geolocation");
case QWebEnginePage::MediaAudioCapture:
return QSL("f_media_audio_capture");
case QWebEnginePage::MediaVideoCapture:
return QSL("f_media_video_capture");
case QWebEnginePage::MediaAudioVideoCapture:
return QSL("f_media_audio_video_capture");
case QWebEnginePage::MouseLock:
return QSL("f_mouse_lock");
case QWebEnginePage::DesktopVideoCapture:
return QSL("f_desktop_video_capture");
case QWebEnginePage::DesktopAudioVideoCapture:
return QSL("f_desktop_audio_video_capture");
default:
qWarning() << "Unknown feature:" << feature;
return QSL("f_notifications");
}
}
QString SiteSettingsManager::webAttributeToSqlColumn(const QWebEngineSettings::WebAttribute attribute) const
{
switch (attribute) {
case QWebEngineSettings::AutoLoadImages:
return QSL("wa_autoload_images");
case QWebEngineSettings::JavascriptEnabled:
return QSL("wa_js_enabled");
case QWebEngineSettings::JavascriptCanOpenWindows:
return QSL("wa_js_open_windows");
case QWebEngineSettings::JavascriptCanAccessClipboard:
return QSL("wa_js_access_clipboard");
case QWebEngineSettings::JavascriptCanPaste:
return QSL("wa_js_can_paste");
case QWebEngineSettings::AllowWindowActivationFromJavaScript:
return QSL("wa_js_window_activation");
case QWebEngineSettings::LocalStorageEnabled:
return QSL("wa_local_storage");
case QWebEngineSettings::FullScreenSupportEnabled:
return QSL("wa_fullscreen_support");
case QWebEngineSettings::AllowRunningInsecureContent:
return QSL("wa_run_insecure_content");
case QWebEngineSettings::PlaybackRequiresUserGesture:
return QSL("wa_playback_needs_gesture");
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
case QWebEngineSettings::ReadingFromCanvasEnabled:
return QSL("wa_reading_from_canvas");
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
case QWebEngineSettings::ForceDarkMode:
return QSL("wa_force_dark_mode");
#endif
default:
qWarning() << "Unknown attribute:" << attribute;
return QSL("wa_js_enabled");
}
}
QList<QWebEngineSettings::WebAttribute> SiteSettingsManager::getSupportedAttribute() const
{
return supportedAttribute;
}
QList<QWebEnginePage::Feature> SiteSettingsManager::getSupportedFeatures() const
{
return supportedFeatures;
}
SiteSettingsManager::SiteSettings SiteSettingsManager::getSiteSettings(QUrl& url)
{
SiteSettings siteSettings;
siteSettings.server = url.host();
if (url.isEmpty()) {
return siteSettings;
}
int index = 0;
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(everythingSql.arg(sqlTable()));
query.addBindValue(url.host());
query.exec();
if (query.next()) {
Permission perm;
for (int i = 0; i < supportedAttribute.size(); ++i, ++index) {
perm = intToPermission(query.value(index).toInt());
siteSettings.attributes[supportedAttribute[i]] = perm;
}
for (int i = 0; i < supportedFeatures.size(); ++i, ++index) {
perm = intToPermission(query.value(index).toInt());
siteSettings.features[supportedFeatures[i]] = perm;
}
siteSettings.AllowCookies = intToPermission(query.value(index++).toInt());
siteSettings.ZoomLevel = query.value(index++).toInt();
}
return siteSettings;
}
void SiteSettingsManager::setSiteSettings(SiteSettingsManager::SiteSettings& siteSettings)
{
if (siteSettings.server.isEmpty()) {
return;
}
auto job = new SqlQueryJob(everythingUpdateSql.arg(sqlTable()), this);
for (int i = 0; i < supportedAttribute.size(); ++i) {
job->addBindValue(siteSettings.attributes[supportedAttribute[i]]);
}
for (int i = 0; i < supportedFeatures.size(); ++i) {
job->addBindValue(siteSettings.features[supportedFeatures[i]]);
}
job->addBindValue(siteSettings.AllowCookies);
job->addBindValue(siteSettings.ZoomLevel);
job->addBindValue(siteSettings.server);
connect(job, &SqlQueryJob::finished, this, [=]() {
if (job->numRowsAffected() == 0) {
auto job = new SqlQueryJob(everythingInsertSql.arg(sqlTable()), this);
for (int i = 0; i < supportedAttribute.size(); ++i) {
job->addBindValue(siteSettings.attributes[supportedAttribute[i]]);
}
for (int i = 0; i < supportedFeatures.size(); ++i) {
job->addBindValue(siteSettings.features[supportedFeatures[i]]);
}
job->addBindValue(siteSettings.AllowCookies);
job->addBindValue(siteSettings.ZoomLevel);
job->addBindValue(siteSettings.server);
job->start();
}
});
job->start();
}
QString SiteSettingsManager::sqlTable()
{
return QSL("site_settings");
}
void SiteSettingsManager::prepareSqls() {
/* Select SQL for QtWE Attributes */
attributesSql = QSL("SELECT ");
for (int i = 0; i < supportedAttribute.size(); ++i) {
if (i > 0) {
attributesSql.append(QSL(", "));
}
attributesSql.append(webAttributeToSqlColumn(supportedAttribute[i]));
}
attributesSql.append(QSL(" FROM %1 WHERE server=?").arg(sqlTable()));
/* Select SQL for SiteSettings */
everythingSql = QSL("SELECT ");
for (int i = 0; i < supportedAttribute.size(); ++i) {
if (i > 0) {
everythingSql.append(QSL(", "));
}
everythingSql.append(webAttributeToSqlColumn(supportedAttribute[i]));
}
for (int i = 0; i < supportedFeatures.size(); ++i) {
everythingSql.append(QSL(", "));
everythingSql.append(featureToSqlColumn(supportedFeatures[i]));
}
everythingSql.append(QSL(", "));
everythingSql.append(optionToSqlColumn(poAllowCookies));
everythingSql.append(QSL(", "));
everythingSql.append(optionToSqlColumn(poZoomLevel));
everythingSql.append(QSL(" FROM %1 WHERE server=?"));
/* Insert SQL for SiteSettings */
everythingInsertSql = QSL("INSERT INTO %1 (");
for (int i = 0; i < supportedAttribute.size(); ++i) {
everythingInsertSql.append(webAttributeToSqlColumn(supportedAttribute[i]));
everythingInsertSql.append(QSL(", "));
}
for (int i = 0; i < supportedFeatures.size(); ++i) {
everythingInsertSql.append(featureToSqlColumn(supportedFeatures[i]));
everythingInsertSql.append(QSL(", "));
}
everythingInsertSql.append(optionToSqlColumn(poAllowCookies));
everythingInsertSql.append(QSL(", "));
everythingInsertSql.append(optionToSqlColumn(poZoomLevel));
everythingInsertSql.append(QSL(", server"));
everythingInsertSql.append(QSL(") Values ("));
/* Index = sum(server, numberOfAttributes, numberOfFeatures, cookies, zoom) */
int index = 1 + supportedAttribute.size() + supportedFeatures.size() + 2;
for (int i = 0; i < index; ++i) {
if (i > 0) {
everythingInsertSql.append(QSL(", "));
}
everythingInsertSql.append(QSL("?"));
}
everythingInsertSql.append(QSL(")"));
/* Update SQL for SiteSettings */
everythingUpdateSql = QSL("UPDATE %1 SET ");
for (int i = 0; i < supportedAttribute.size(); ++i) {
everythingUpdateSql.append(webAttributeToSqlColumn(supportedAttribute[i]));
everythingUpdateSql.append(QSL("=?, "));
}
for (int i = 0; i < supportedFeatures.size(); ++i) {
everythingUpdateSql.append(featureToSqlColumn(supportedFeatures[i]));
everythingUpdateSql.append(QSL("=?, "));
}
everythingUpdateSql.append(optionToSqlColumn(poAllowCookies));
everythingUpdateSql.append(QSL("=?, "));
everythingUpdateSql.append(optionToSqlColumn(poZoomLevel));
everythingUpdateSql.append(QSL("=? "));
everythingUpdateSql.append(QSL(" WHERE server=?"));
}

View File

@ -0,0 +1,141 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2022 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef SITESETTINGS_MANAGER_H
#define SITESETTINGS_MANAGER_H
#include "qzcommon.h"
#include <QWebEnginePage>
#include <QWebEngineSettings>
class QUrl;
class FALKON_EXPORT SiteSettingsManager : public QObject
{
Q_OBJECT
public:
enum Permission {
Default = 0,
Allow = 1,
Deny = 2,
Ask = 3,
};
Q_ENUM(Permission);
/* Browser options */
enum PageOptions {
poAllowCookies,
poZoomLevel,
};
Q_ENUM(PageOptions);
struct SiteSettings
{
Permission AllowCookies = Default;
int ZoomLevel = -1;
QMap<QWebEngineSettings::WebAttribute, Permission> attributes; /* Enable disable soem feature eg. Javascript, Images etc */
QMap<QWebEnginePage::Feature, Permission> features; /* HTML permissions */
QString server;
bool operator==(const SiteSettings &other) const {
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
if (it.value() != other.attributes[it.key()]) {
return false;
}
}
for (auto it = features.begin(); it != features.end(); ++it) {
if (it.value() != other.features[it.key()]) {
return false;
}
}
if ((AllowCookies != other.AllowCookies)
|| (ZoomLevel != other.ZoomLevel)
|| (server != other.server)
) {
return false;
}
return true;
}
};
explicit SiteSettingsManager(QObject *parent = nullptr);
~SiteSettingsManager();
void loadSettings();
void saveSettings();
QHash<QWebEngineSettings::WebAttribute, bool> getWebAttributes(const QUrl &url);
Permission getPermission(const QString &column, const QString &host);
Permission getPermission(const PageOptions option, const QString &host);
Permission getPermission(const QWebEnginePage::Feature feature, const QString &host);
Permission getPermission(const QWebEngineSettings::WebAttribute attribute, const QString &host);
Permission getPermission(const QString &column, const QUrl &url);
Permission getPermission(const PageOptions option, const QUrl &url);
Permission getPermission(const QWebEnginePage::Feature feature, const QUrl &url);
Permission getPermission(const QWebEngineSettings::WebAttribute attribute, const QUrl &url);
void setOption(const QString &column, const QUrl &url, const int value);
void setOption(const PageOptions option, const QUrl &url, const int value);
void setOption(const QWebEnginePage::Feature &feature, const QUrl &url, const Permission value);
void setOption(const QWebEngineSettings::WebAttribute &attribute, const QUrl &url, const Permission value);
Permission getDefaultPermission(const PageOptions option);
Permission getDefaultPermission(const QWebEnginePage::Feature feature) const;
Permission getDefaultPermission(const QWebEngineSettings::WebAttribute attribute) const;
QString getOptionName(const SiteSettingsManager::PageOptions option) const;
QString getOptionName(const QWebEnginePage::Feature feature) const;
QString getOptionName(const QWebEngineSettings::WebAttribute attribute) const;
QString getPermissionName(const Permission permission) const;
QString webAttributeToSqlColumn(const QWebEngineSettings::WebAttribute attribute) const;
QString featureToSqlColumn(const QWebEnginePage::Feature feature) const;
QString optionToSqlColumn(const PageOptions option) const;
QList<QWebEngineSettings::WebAttribute> getSupportedAttribute() const;
QList<QWebEnginePage::Feature> getSupportedFeatures() const;
SiteSettings getSiteSettings(QUrl &url);
void setSiteSettings(SiteSettings &siteSettings);
QString sqlTable();
Permission intToPermission(const int permission) const;
private:
void prepareSqls();
QMap<QWebEnginePage::Feature, Permission> defaultFeatures;
QString attributesSql;
QString everythingSql;
QString everythingInsertSql;
QString everythingUpdateSql;
};
using SiteSettings = SiteSettingsManager::SiteSettings;
// Hint to QVector to use std::realloc on item moving
Q_DECLARE_TYPEINFO(SiteSettings, Q_MOVABLE_TYPE);
#endif // SITESETTINGS_MANAGER_H

View File

@ -43,13 +43,15 @@
#include "useragentdialog.h" #include "useragentdialog.h"
#include "registerqappassociation.h" #include "registerqappassociation.h"
#include "profilemanager.h" #include "profilemanager.h"
#include "html5permissions/html5permissionsdialog.h"
#include "certificatemanager.h" #include "certificatemanager.h"
#include "searchenginesdialog.h" #include "searchenginesdialog.h"
#include "webscrollbarmanager.h" #include "webscrollbarmanager.h"
#include "protocolhandlerdialog.h" #include "protocolhandlerdialog.h"
#include "schememanager.h" #include "schememanager.h"
#include "../config.h" #include "../config.h"
#include "sitesettingsmanager.h"
#include "sitesettingsattributesitem.h"
#include "sitesettingshtml5item.h"
#include <QSettings> #include <QSettings>
#include <QInputDialog> #include <QInputDialog>
@ -295,6 +297,16 @@ Preferences::Preferences(BrowserWindow* window)
ui->intPDFViewer->setEnabled(ui->allowPlugins->isChecked()); ui->intPDFViewer->setEnabled(ui->allowPlugins->isChecked());
ui->screenCaptureEnabled->setChecked(settings.value(QSL("screenCaptureEnabled"), false).toBool()); ui->screenCaptureEnabled->setChecked(settings.value(QSL("screenCaptureEnabled"), false).toBool());
ui->hardwareAccel->setChecked(settings.value(QSL("hardwareAccel"), false).toBool()); ui->hardwareAccel->setChecked(settings.value(QSL("hardwareAccel"), false).toBool());
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
ui->readingFromCanvasEnabled->setChecked(settings.value(QSL("readingFromCanvasEnabled"), false).toBool());
#else
ui->readingFromCanvasEnabled->hide();
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
ui->forceDarkMode->setChecked(settings.value(QSL("forceDarkMode"), false).toBool());
#else
ui->forceDarkMode->hide();
#endif
const auto levels = WebView::zoomLevels(); const auto levels = WebView::zoomLevels();
for (int level : levels) { for (int level : levels) {
@ -325,6 +337,25 @@ Preferences::Preferences(BrowserWindow* window)
} }
connect(ui->saveHistory, &QAbstractButton::toggled, this, &Preferences::saveHistoryChanged); connect(ui->saveHistory, &QAbstractButton::toggled, this, &Preferences::saveHistoryChanged);
/* SiteSettings - WebAttributes */
const auto supportedAttribute = mApp->siteSettingsManager()->getSupportedAttribute();
for (const auto &attribute : supportedAttribute) {
auto* listItem = new QListWidgetItem(ui->siteSettingsList);
auto* optionItem = new SiteSettingsAttributesItem(attribute, this);
ui->siteSettingsList->setItemWidget(listItem, optionItem);
listItem->setSizeHint(optionItem->sizeHint());
}
/* SiteSettings - HTML5 features */
const auto supportedFeatures = mApp->siteSettingsManager()->getSupportedFeatures();
for (const auto &feature : supportedFeatures) {
auto* listItem = new QListWidgetItem(ui->siteSettingsHtml5List);
auto* optionItem = new SiteSettingsHtml5Item(feature, this);
ui->siteSettingsHtml5List->setItemWidget(listItem, optionItem);
listItem->setSizeHint(optionItem->sizeHint());
}
// Html5Storage // Html5Storage
ui->html5storage->setChecked(settings.value(QSL("HTML5StorageEnabled"), true).toBool()); ui->html5storage->setChecked(settings.value(QSL("HTML5StorageEnabled"), true).toBool());
ui->deleteHtml5storageOnClose->setChecked(settings.value(QSL("deleteHTML5StorageOnClose"), false).toBool()); ui->deleteHtml5storageOnClose->setChecked(settings.value(QSL("deleteHTML5StorageOnClose"), false).toBool());
@ -514,7 +545,6 @@ Preferences::Preferences(BrowserWindow* window)
//CONNECTS //CONNECTS
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &Preferences::buttonClicked); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &Preferences::buttonClicked);
connect(ui->cookieManagerBut, &QAbstractButton::clicked, this, &Preferences::showCookieManager); connect(ui->cookieManagerBut, &QAbstractButton::clicked, this, &Preferences::showCookieManager);
connect(ui->html5permissions, &QAbstractButton::clicked, this, &Preferences::showHtml5Permissions);
connect(ui->preferredLanguages, &QAbstractButton::clicked, this, &Preferences::showAcceptLanguage); connect(ui->preferredLanguages, &QAbstractButton::clicked, this, &Preferences::showAcceptLanguage);
connect(ui->deleteHtml5storage, &QAbstractButton::clicked, this, &Preferences::deleteHtml5storage); connect(ui->deleteHtml5storage, &QAbstractButton::clicked, this, &Preferences::deleteHtml5storage);
connect(ui->uaManager, &QAbstractButton::clicked, this, &Preferences::openUserAgentManager); connect(ui->uaManager, &QAbstractButton::clicked, this, &Preferences::openUserAgentManager);
@ -718,12 +748,6 @@ void Preferences::showCookieManager()
dialog->show(); dialog->show();
} }
void Preferences::showHtml5Permissions()
{
auto* dialog = new HTML5PermissionsDialog(this);
dialog->open();
}
void Preferences::openJsOptions() void Preferences::openJsOptions()
{ {
auto* dialog = new JsOptions(this); auto* dialog = new JsOptions(this);
@ -986,6 +1010,12 @@ void Preferences::saveSettings()
settings.setValue(QSL("intPDFViewer"), ui->intPDFViewer->isChecked()); settings.setValue(QSL("intPDFViewer"), ui->intPDFViewer->isChecked());
settings.setValue(QSL("screenCaptureEnabled"), ui->screenCaptureEnabled->isChecked()); settings.setValue(QSL("screenCaptureEnabled"), ui->screenCaptureEnabled->isChecked());
settings.setValue(QSL("hardwareAccel"), ui->hardwareAccel->isChecked()); settings.setValue(QSL("hardwareAccel"), ui->hardwareAccel->isChecked());
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
settings.setValue(QSL("readingFromCanvasEnabled"), ui->readingFromCanvasEnabled->isChecked());
#endif
#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
settings.setValue(QSL("forceDarkMode"), ui->forceDarkMode->isChecked());
#endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
settings.setValue(QSL("CheckDefaultBrowser"), ui->checkDefaultBrowser->isChecked()); settings.setValue(QSL("CheckDefaultBrowser"), ui->checkDefaultBrowser->isChecked());
#endif #endif
@ -1073,11 +1103,21 @@ void Preferences::saveSettings()
settings.setValue(QSL("Password"), ui->proxyPassword->text()); settings.setValue(QSL("Password"), ui->proxyPassword->text());
settings.endGroup(); settings.endGroup();
//SiteSettings
settings.beginGroup(QSL("Site-Settings"));
/* HTML5 Features */
for (int i = 0; i < ui->siteSettingsHtml5List->count(); ++i) {
auto *item = static_cast<SiteSettingsHtml5Item*>(ui->siteSettingsHtml5List->itemWidget(ui->siteSettingsHtml5List->item(i)));
settings.setValue(mApp->siteSettingsManager()->featureToSqlColumn(item->feature()), item->permission());
}
settings.endGroup();
ProfileManager::setStartingProfile(ui->startProfile->currentText()); ProfileManager::setStartingProfile(ui->startProfile->currentText());
m_pluginsList->save(); m_pluginsList->save();
m_themesManager->save(); m_themesManager->save();
mApp->cookieJar()->loadSettings(); mApp->cookieJar()->loadSettings();
mApp->siteSettingsManager()->loadSettings();
mApp->history()->loadSettings(); mApp->history()->loadSettings();
mApp->reloadSettings(); mApp->reloadSettings();
mApp->desktopNotifications()->loadSettings(); mApp->desktopNotifications()->loadSettings();

View File

@ -54,7 +54,6 @@ private Q_SLOTS:
void chooseDownPath(); void chooseDownPath();
void showCookieManager(); void showCookieManager();
void showHtml5Permissions();
void useActualHomepage(); void useActualHomepage();
void useActualNewTab(); void useActualNewTab();
void showAcceptLanguage(); void showAcceptLanguage();

View File

@ -6,14 +6,21 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>840</width> <width>1035</width>
<height>550</height> <height>727</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Preferences</string> <string>Preferences</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="4" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="5"> <item row="0" column="0" rowspan="5">
<widget class="QListWidget" name="listWidget"> <widget class="QListWidget" name="listWidget">
<property name="minimumSize"> <property name="minimumSize">
@ -132,6 +139,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2"> <item row="2" column="1" colspan="2">
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
<property name="frameShape"> <property name="frameShape">
@ -145,8 +159,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>582</width> <width>783</width>
<height>476</height> <height>651</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
@ -1117,6 +1131,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="readingFromCanvasEnabled">
<property name="text">
<string>Allow reading from canvas</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="forceDarkMode">
<property name="text">
<string>Force dark mode</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
@ -2008,147 +2036,154 @@
</widget> </widget>
<widget class="QWidget" name="privacyPage"> <widget class="QWidget" name="privacyPage">
<layout class="QGridLayout" name="gridLayout_12"> <layout class="QGridLayout" name="gridLayout_12">
<item row="8" column="0" colspan="3"> <item row="20" column="1">
<widget class="QLabel" name="label_12"> <widget class="QTabWidget" name="tabWidget_4">
<property name="text"> <property name="currentIndex">
<string>&lt;b&gt;Cookies&lt;/b&gt;</string> <number>0</number>
</property>
</widget>
</item>
<item row="20" column="0" colspan="4">
<widget class="QLabel" name="label_50">
<property name="text">
<string>&lt;b&gt;Other&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="28" column="0" colspan="4">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="16" column="3">
<widget class="QPushButton" name="jsOptionsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JavaScript options</string>
</property>
</widget>
</item>
<item row="15" column="0" colspan="4">
<widget class="QLabel" name="label_61">
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="text">
<string>&lt;b&gt;JavaScript&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="12" column="3">
<widget class="QPushButton" name="cookieManagerBut">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cookies Manager</string>
</property>
</widget>
</item>
<item row="16" column="0" colspan="3">
<widget class="QLabel" name="label_25">
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="text">
<string>Manage JavaScript privacy options</string>
</property>
</widget>
</item>
<item row="22" column="0">
<spacer name="horizontalSpacer_20">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="19" column="0" colspan="3">
<widget class="QLabel" name="label_63">
<property name="text">
<string>Manage HTML5 permissions</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Manage Cookies</string>
</property>
</widget>
</item>
<item row="8" column="3">
<spacer name="horizontalSpacer_22">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="18" column="0" colspan="4">
<widget class="QLabel" name="label_62">
<property name="text">
<string>&lt;b&gt;HTML5 Permissions&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="19" column="3">
<widget class="QPushButton" name="html5permissions">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>HTML5 Permissions</string>
</property>
</widget>
</item>
<item row="22" column="1" colspan="3">
<widget class="QCheckBox" name="doNotTrack">
<property name="text">
<string>Send Do Not Track header to servers</string>
</property> </property>
<widget class="QWidget" name="tab_9">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_24">
<item row="1" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Manage Cookies</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="cookieManagerBut">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cookies Manager</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_22">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="label_61">
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="text">
<string>&lt;b&gt;JavaScript&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="jsOptionsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>JavaScript options</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QCheckBox" name="doNotTrack">
<property name="text">
<string>Send Do Not Track header to servers</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>&lt;b&gt;Cookies&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="8" column="0">
<spacer name="horizontalSpacer_20">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_25">
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="text">
<string>Manage JavaScript privacy options</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_50">
<property name="text">
<string>&lt;b&gt;Other&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_10">
<attribute name="title">
<string>HTML5 Permissions</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QListWidget" name="siteSettingsHtml5List"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_11">
<attribute name="title">
<string>Site Settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QListWidget" name="siteSettingsList"/>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -2435,8 +2470,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>560</width> <width>98</width>
<height>80</height> <height>29</height>
</rect> </rect>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_14"> <layout class="QHBoxLayout" name="horizontalLayout_14">
@ -2840,20 +2875,6 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="3" column="1" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>

View File

@ -0,0 +1,40 @@
/*
* Falkon - Permission item for web attributes for preferences
* SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "sitesettingsattributesitem.h"
#include "ui_sitesettingsattributesitem.h"
#include "mainapplication.h"
#include "sitesettingsmanager.h"
#include "sitesettingsbrowsedialog.h"
SiteSettingsAttributesItem::SiteSettingsAttributesItem(const QWebEngineSettings::WebAttribute a_attribute, QWidget* parent)
: QWidget(parent)
, m_attribute(a_attribute)
, m_ui(new Ui::SiteSettingsAttributesItem)
{
m_ui->setupUi(this);
m_ui->label->setText(mApp->siteSettingsManager()->getOptionName(m_attribute));
connect(m_ui->browseButton, &QPushButton::clicked, this, &SiteSettingsAttributesItem::showBrowseDialog);
}
SiteSettingsAttributesItem::~SiteSettingsAttributesItem() = default;
void SiteSettingsAttributesItem::showBrowseDialog()
{
QString sqlColumn = mApp->siteSettingsManager()->webAttributeToSqlColumn(m_attribute);
QString name = m_ui->label->text();
auto* dialog = new SiteSettingsBrowseDialog(name, sqlColumn, this);
dialog->hideAskButton();
dialog->open();
}
QWebEngineSettings::WebAttribute SiteSettingsAttributesItem::attribute() const
{
return m_attribute;
}

View File

@ -0,0 +1,40 @@
/*
* Falkon - Permission item for web attributes for preferences
* SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef SITESETTINGSATTRIBUTESITEM_H
#define SITESETTINGSATTRIBUTESITEM_H
#include <QWidget>
#include <QScopedPointer>
#include <QWebEngineSettings>
namespace Ui
{
class SiteSettingsAttributesItem;
}
class SiteSettingsAttributesItem : public QWidget
{
Q_OBJECT
Q_PROPERTY(QWebEngineSettings::WebAttribute m_attribute READ attribute)
public:
SiteSettingsAttributesItem(const QWebEngineSettings::WebAttribute a_attribute, QWidget* parent = nullptr);
~SiteSettingsAttributesItem();
QWebEngineSettings::WebAttribute attribute() const;
public Q_SLOTS:
void showBrowseDialog();
private:
QWebEngineSettings::WebAttribute m_attribute;
private:
QScopedPointer<Ui::SiteSettingsAttributesItem> m_ui;
};
#endif // SITESETTINGSATTRIBUTESITEM_H

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SiteSettingsAttributesItem</class>
<widget class="QWidget" name="SiteSettingsAttributesItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>61</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,90 @@
// Falkon - SiteSettings permission browser dialog
// SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "sitesettingsbrowsedialog.h"
#include "ui_sitesettingsbrowsedialog.h"
#include "mainapplication.h"
#include "sqldatabase.h"
const int rolePermission = Qt::UserRole + 10;
SiteSettingsBrowseDialog::SiteSettingsBrowseDialog(QString &name, QString &sqlColumn, QWidget* parent)
: QDialog(parent)
, m_ui(new Ui::SiteSettingsBrowseDialog)
, m_sqlColumn(sqlColumn)
{
m_ui->setupUi(this);
m_ui->nameLabel->setText(name);
loadItems();
m_ui->treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
connect(m_ui->askButton, &QPushButton::clicked, this, [=]() { setPermission(SiteSettingsManager::Ask); });
connect(m_ui->allowButton, &QPushButton::clicked, this, [=]() { setPermission(SiteSettingsManager::Allow); });
connect(m_ui->denyButton, &QPushButton::clicked, this, [=]() { setPermission(SiteSettingsManager::Deny); });
connect(m_ui->defaultButton, &QPushButton::clicked, this, [=]() { setPermission(SiteSettingsManager::Default); });
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &SiteSettingsBrowseDialog::storeChanges);
}
void SiteSettingsBrowseDialog::loadItems()
{
QSqlDatabase db = SqlDatabase::instance()->database();
QString sqlTable = mApp->siteSettingsManager()->sqlTable();
QSqlQuery query(SqlDatabase::instance()->database());
query.prepare(QSL("SELECT server, %2 FROM %1 WHERE %2!=?").arg(sqlTable, m_sqlColumn));
query.addBindValue(SiteSettingsManager::Default);
query.exec();
while (query.next()) {
QString server = query.value(0).toString();
auto permission = mApp->siteSettingsManager()->intToPermission(query.value(1).toInt());
QString permissionName = mApp->siteSettingsManager()->getPermissionName(permission);
auto* item = new QTreeWidgetItem(m_ui->treeWidget);
item->setText(0, server);
item->setText(1, permissionName);
item->setData(0, rolePermission, permission);
m_ui->treeWidget->addTopLevelItem(item);
}
}
void SiteSettingsBrowseDialog::storeChanges()
{
QUrl url;
for (QHash<QString, int>::iterator it = m_listModifications.begin(); it != m_listModifications.end(); ++it) {
url.setHost(it.key());
mApp->siteSettingsManager()->setOption(m_sqlColumn, url, it.value());
}
}
void SiteSettingsBrowseDialog::setPermission(const SiteSettingsManager::Permission permission)
{
QTreeWidgetItem* item = m_ui->treeWidget->currentItem();
if (!item) {
return;
}
const QString server = item->text(0);
auto itemPermission = static_cast<SiteSettingsManager::Permission>(item->data(0, Qt::UserRole + 10).toInt());
if (permission == itemPermission) {
m_listModifications.remove(server);
}
QString permissionName = mApp->siteSettingsManager()->getPermissionName(permission);
m_listModifications[server] = permission;
item->setText(1, permissionName);
}
void SiteSettingsBrowseDialog::hideAskButton()
{
m_ui->askButton->hide();
}
SiteSettingsBrowseDialog::~SiteSettingsBrowseDialog() = default;

View File

@ -0,0 +1,40 @@
// Falkon - SiteSettings permission browser dialog
// SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef SITESETTINGSBROWSEDIALOG_H
#define SITESETTINGSBROWSEDIALOG_H
#include "sitesettingsmanager.h"
#include <QDialog>
#include <QScopedPointer>
namespace Ui
{
class SiteSettingsBrowseDialog;
}
class SiteSettingsBrowseDialog : public QDialog
{
Q_OBJECT
public:
SiteSettingsBrowseDialog(QString &name, QString &sqlColumn, QWidget* parent = nullptr);
~SiteSettingsBrowseDialog();
void setPermission(const SiteSettingsManager::Permission permission);
void hideAskButton();
public Q_SLOTS:
void storeChanges();
private:
void loadItems();
QScopedPointer<Ui::SiteSettingsBrowseDialog> m_ui;
QHash<QString, int> m_listModifications;
QString m_sqlColumn;
};
#endif // SITESETTINGSBROWSEDIALOG_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>HTML5PermissionsDialog</class> <class>SiteSettingsBrowseDialog</class>
<widget class="QDialog" name="HTML5PermissionsDialog"> <widget class="QDialog" name="SiteSettingsBrowseDialog">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -11,43 +11,9 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>HTML5 Permissions</string> <string>Site Permissions</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="remove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QTreeWidget" name="treeWidget"> <widget class="QTreeWidget" name="treeWidget">
<property name="indentation"> <property name="indentation">
@ -71,74 +37,68 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="0" column="0" colspan="2"> <item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QPushButton" name="askButton">
<property name="text"> <property name="text">
<string>Permission for:</string> <string>Ask</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="feature"> <widget class="QPushButton" name="allowButton">
<item> <property name="text">
<property name="text"> <string>Allow</string>
<string>Notifications</string> </property>
</property>
</item>
<item>
<property name="text">
<string>Geolocation</string>
</property>
</item>
<item>
<property name="text">
<string>Microphone</string>
</property>
</item>
<item>
<property name="text">
<string>Camera</string>
</property>
</item>
<item>
<property name="text">
<string>Microphone and Camera</string>
</property>
</item>
<item>
<property name="text">
<string>Hide Pointer</string>
</property>
</item>
<item>
<property name="text">
<string>Display Capture</string>
</property>
</item>
<item>
<property name="text">
<string>Display and Audio Capture</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <widget class="QPushButton" name="denyButton">
<property name="text">
<string>Deny</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="defaultButton">
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>20</width>
<height>20</height> <height>40</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>
@ -146,7 +106,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>HTML5PermissionsDialog</receiver> <receiver>SiteSettingsBrowseDialog</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -162,7 +122,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>HTML5PermissionsDialog</receiver> <receiver>SiteSettingsBrowseDialog</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -0,0 +1,73 @@
/*
* Falkon - Permission item for HTML5 features for preferences
* SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "sitesettingshtml5item.h"
#include "ui_sitesettingshtml5item.h"
#include "mainapplication.h"
#include "sitesettingsmanager.h"
#include "sitesettingsbrowsedialog.h"
SiteSettingsHtml5Item::SiteSettingsHtml5Item(const QWebEnginePage::Feature a_feature, QWidget* parent)
: QWidget(parent)
, m_feature(a_feature)
, m_ui(new Ui::SiteSettingsHtml5Item)
{
m_ui->setupUi(this);
m_ui->defaultPermissionCombo->addItem(
mApp->siteSettingsManager()->getPermissionName(SiteSettingsManager::Ask),
SiteSettingsManager::Ask
);
m_ui->defaultPermissionCombo->addItem(
mApp->siteSettingsManager()->getPermissionName(SiteSettingsManager::Allow),
SiteSettingsManager::Allow
);
m_ui->defaultPermissionCombo->addItem(
mApp->siteSettingsManager()->getPermissionName(SiteSettingsManager::Deny),
SiteSettingsManager::Deny
);
setPermission();
m_ui->label->setText(mApp->siteSettingsManager()->getOptionName(m_feature));
connect(m_ui->browseButton, &QPushButton::clicked, this, &SiteSettingsHtml5Item::showBrowseDialog);
}
SiteSettingsHtml5Item::~SiteSettingsHtml5Item() = default;
void SiteSettingsHtml5Item::showBrowseDialog()
{
QString sqlColumn = mApp->siteSettingsManager()->featureToSqlColumn(m_feature);
QString name = m_ui->label->text();
auto* dialog = new SiteSettingsBrowseDialog(name, sqlColumn, this);
dialog->open();
}
QWebEnginePage::Feature SiteSettingsHtml5Item::feature() const
{
return m_feature;
}
SiteSettingsManager::Permission SiteSettingsHtml5Item::permission() const
{
QVariant data = m_ui->defaultPermissionCombo->currentData();
return data.value<SiteSettingsManager::Permission>();
}
void SiteSettingsHtml5Item::setPermission()
{
auto defaultPermission = mApp->siteSettingsManager()->getDefaultPermission(m_feature);
int index = m_ui->defaultPermissionCombo->findData(defaultPermission);
if (index == -1) {
qWarning() << "Unknown permission" << defaultPermission;
return;
}
m_ui->defaultPermissionCombo->setCurrentIndex(index);
}

View File

@ -0,0 +1,45 @@
/*
* Falkon - Permission item for HTML5 features for preferences
* SPDX-FileCopyrightText: 2024 Juraj Oravec <jurajoravec@mailo.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef SITESETTINGSHTML5ITEM_H
#define SITESETTINGSHTML5ITEM_H
#include "sitesettingsmanager.h"
#include <QWidget>
#include <QScopedPointer>
#include <QWebEnginePage>
namespace Ui
{
class SiteSettingsHtml5Item;
}
class SiteSettingsHtml5Item : public QWidget
{
Q_OBJECT
Q_PROPERTY(QWebEnginePage::Feature feature READ feature)
public:
SiteSettingsHtml5Item(const QWebEnginePage::Feature a_feature, QWidget* parent = nullptr);
~SiteSettingsHtml5Item();
QWebEnginePage::Feature feature() const;
SiteSettingsManager::Permission permission() const;
public Q_SLOTS:
void showBrowseDialog();
private:
QWebEnginePage::Feature m_feature;
void setPermission();
private:
QScopedPointer<Ui::SiteSettingsHtml5Item> m_ui;
};
#endif // SITESETTINGSHTML5ITEM_H

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SiteSettingsHtml5Item</class>
<widget class="QWidget" name="SiteSettingsHtml5Item">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>61</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="defaultPermissionCombo"/>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,190 +0,0 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "html5permissionsdialog.h"
#include "ui_html5permissionsdialog.h"
#include "settings.h"
#include "mainapplication.h"
#include "html5permissionsmanager.h"
#include <QtWebEngineWidgetsVersion>
HTML5PermissionsDialog::HTML5PermissionsDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::HTML5PermissionsDialog)
{
setAttribute(Qt::WA_DeleteOnClose);
ui->setupUi(this);
loadSettings();
ui->treeWidget->header()->resizeSection(0, 220);
connect(ui->remove, &QPushButton::clicked, this, &HTML5PermissionsDialog::removeEntry);
connect(ui->feature, SIGNAL(currentIndexChanged(int)), this, SLOT(featureIndexChanged()));
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &HTML5PermissionsDialog::saveSettings);
showFeaturePermissions(currentFeature());
}
HTML5PermissionsDialog::~HTML5PermissionsDialog()
{
delete ui;
}
void HTML5PermissionsDialog::showFeaturePermissions(QWebEnginePage::Feature feature)
{
if (!m_granted.contains(feature) || !m_denied.contains(feature)) {
return;
}
ui->treeWidget->clear();
const auto grantedSites = m_granted.value(feature);
for (const QString &site : grantedSites) {
auto* item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, site);
item->setText(1, tr("Allow"));
item->setData(0, Qt::UserRole + 10, Allow);
ui->treeWidget->addTopLevelItem(item);
}
const auto deniedSites = m_denied.value(feature);
for (const QString &site : deniedSites) {
auto* item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, site);
item->setText(1, tr("Deny"));
item->setData(0, Qt::UserRole + 10, Deny);
ui->treeWidget->addTopLevelItem(item);
}
}
void HTML5PermissionsDialog::featureIndexChanged()
{
showFeaturePermissions(currentFeature());
}
void HTML5PermissionsDialog::removeEntry()
{
QTreeWidgetItem* item = ui->treeWidget->currentItem();
if (!item) {
return;
}
Role role = static_cast<Role>(item->data(0, Qt::UserRole + 10).toInt());
const QString origin = item->text(0);
if (role == Allow)
m_granted[currentFeature()].removeOne(origin);
else
m_denied[currentFeature()].removeOne(origin);
delete item;
}
QWebEnginePage::Feature HTML5PermissionsDialog::currentFeature() const
{
switch (ui->feature->currentIndex()) {
case 0:
return QWebEnginePage::Notifications;
case 1:
return QWebEnginePage::Geolocation;
case 2:
return QWebEnginePage::MediaAudioCapture;
case 3:
return QWebEnginePage::MediaVideoCapture;
case 4:
return QWebEnginePage::MediaAudioVideoCapture;
case 5:
return QWebEnginePage::MouseLock;
case 6:
return QWebEnginePage::DesktopVideoCapture;
case 7:
return QWebEnginePage::DesktopAudioVideoCapture;
default:
Q_UNREACHABLE();
return QWebEnginePage::Notifications;
}
}
void HTML5PermissionsDialog::loadSettings()
{
Settings settings;
settings.beginGroup(QSL("HTML5Notifications"));
m_granted[QWebEnginePage::Notifications] = settings.value(QSL("NotificationsGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::Notifications] = settings.value(QSL("NotificationsDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::Geolocation] = settings.value(QSL("GeolocationGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::Geolocation] = settings.value(QSL("GeolocationDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaAudioCapture] = settings.value(QSL("MediaAudioCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaAudioCapture] = settings.value(QSL("MediaAudioCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaVideoCapture] = settings.value(QSL("MediaVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaVideoCapture] = settings.value(QSL("MediaVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaAudioVideoCapture] = settings.value(QSL("MediaAudioVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaAudioVideoCapture] = settings.value(QSL("MediaAudioVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MouseLock] = settings.value(QSL("MouseLockGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MouseLock] = settings.value(QSL("MouseLockDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::DesktopVideoCapture] = settings.value(QSL("DesktopVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::DesktopVideoCapture] = settings.value(QSL("DesktopVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::DesktopAudioVideoCapture] = settings.value(QSL("DesktopAudioVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::DesktopAudioVideoCapture] = settings.value(QSL("DesktopAudioVideoCaptureDenied"), QStringList()).toStringList();
settings.endGroup();
}
void HTML5PermissionsDialog::saveSettings()
{
Settings settings;
settings.beginGroup(QSL("HTML5Notifications"));
settings.setValue(QSL("NotificationsGranted"), m_granted[QWebEnginePage::Notifications]);
settings.setValue(QSL("NotificationsDenied"), m_denied[QWebEnginePage::Notifications]);
settings.setValue(QSL("GeolocationGranted"), m_granted[QWebEnginePage::Geolocation]);
settings.setValue(QSL("GeolocationDenied"), m_denied[QWebEnginePage::Geolocation]);
settings.setValue(QSL("MediaAudioCaptureGranted"), m_granted[QWebEnginePage::MediaAudioCapture]);
settings.setValue(QSL("MediaAudioCaptureDenied"), m_denied[QWebEnginePage::MediaAudioCapture]);
settings.setValue(QSL("MediaVideoCaptureGranted"), m_granted[QWebEnginePage::MediaVideoCapture]);
settings.setValue(QSL("MediaVideoCaptureDenied"), m_denied[QWebEnginePage::MediaVideoCapture]);
settings.setValue(QSL("MediaAudioVideoCaptureGranted"), m_granted[QWebEnginePage::MediaAudioVideoCapture]);
settings.setValue(QSL("MediaAudioVideoCaptureDenied"), m_denied[QWebEnginePage::MediaAudioVideoCapture]);
settings.setValue(QSL("MouseLockGranted"), m_granted[QWebEnginePage::MouseLock]);
settings.setValue(QSL("MouseLockDenied"), m_denied[QWebEnginePage::MouseLock]);
settings.setValue(QSL("DesktopVideoCaptureGranted"), m_granted[QWebEnginePage::DesktopVideoCapture]);
settings.setValue(QSL("DesktopVideoCaptureDenied"), m_denied[QWebEnginePage::DesktopVideoCapture]);
settings.setValue(QSL("DesktopAudioVideoCaptureGranted"), m_granted[QWebEnginePage::DesktopAudioVideoCapture]);
settings.setValue(QSL("DesktopAudioVideoCaptureDenied"), m_denied[QWebEnginePage::DesktopAudioVideoCapture]);
settings.endGroup();
mApp->html5PermissionsManager()->loadSettings();
}

View File

@ -19,6 +19,8 @@
#include "html5permissionsnotification.h" #include "html5permissionsnotification.h"
#include "settings.h" #include "settings.h"
#include "webview.h" #include "webview.h"
#include "mainapplication.h"
#include "sitesettingsmanager.h"
#include <QtWebEngineWidgetsVersion> #include <QtWebEngineWidgetsVersion>
@ -26,7 +28,6 @@
HTML5PermissionsManager::HTML5PermissionsManager(QObject* parent) HTML5PermissionsManager::HTML5PermissionsManager(QObject* parent)
: QObject(parent) : QObject(parent)
{ {
loadSettings();
} }
void HTML5PermissionsManager::requestPermissions(WebPage* page, const QUrl &origin, const QWebEnginePage::Feature &feature) void HTML5PermissionsManager::requestPermissions(WebPage* page, const QUrl &origin, const QWebEnginePage::Feature &feature)
@ -35,26 +36,26 @@ void HTML5PermissionsManager::requestPermissions(WebPage* page, const QUrl &orig
return; return;
} }
if (!m_granted.contains(feature) || !m_denied.contains(feature)) { if (!mApp->siteSettingsManager()->getSupportedFeatures().contains(feature)) {
qWarning() << "HTML5PermissionsManager: Unknown feature" << feature; qWarning() << "HTML5PermissionsManager: Unknown feature" << feature;
return; return;
} }
// Permission granted auto permission = mApp->siteSettingsManager()->getPermission(feature, origin);
if (m_granted.value(feature).contains(origin.toString())) { if (permission == SiteSettingsManager::Default) {
permission = mApp->siteSettingsManager()->getDefaultPermission(feature);
}
if (permission == SiteSettingsManager::Allow) {
page->setFeaturePermission(origin, feature, QWebEnginePage::PermissionGrantedByUser); page->setFeaturePermission(origin, feature, QWebEnginePage::PermissionGrantedByUser);
return;
} }
else if (permission == SiteSettingsManager::Deny) {
// Permission denied
if (m_denied.value(feature).contains(origin.toString())) {
page->setFeaturePermission(origin, feature, QWebEnginePage::PermissionDeniedByUser); page->setFeaturePermission(origin, feature, QWebEnginePage::PermissionDeniedByUser);
return;
} }
else {
// Ask user for permission auto* notif = new HTML5PermissionsNotification(origin, page, feature);
auto* notif = new HTML5PermissionsNotification(origin, page, feature); page->view()->addNotification(notif);
page->view()->addNotification(notif); }
} }
void HTML5PermissionsManager::rememberPermissions(const QUrl &origin, const QWebEnginePage::Feature &feature, void HTML5PermissionsManager::rememberPermissions(const QUrl &origin, const QWebEnginePage::Feature &feature,
@ -65,75 +66,9 @@ void HTML5PermissionsManager::rememberPermissions(const QUrl &origin, const QWeb
} }
if (policy == QWebEnginePage::PermissionGrantedByUser) { if (policy == QWebEnginePage::PermissionGrantedByUser) {
m_granted[feature].append(origin.toString()); mApp->siteSettingsManager()->setOption(feature, origin, SiteSettingsManager::Allow);
} }
else { else {
m_denied[feature].append(origin.toString()); mApp->siteSettingsManager()->setOption(feature, origin, SiteSettingsManager::Deny);
} }
saveSettings();
}
void HTML5PermissionsManager::loadSettings()
{
Settings settings;
settings.beginGroup(QSL("HTML5Notifications"));
m_granted[QWebEnginePage::Notifications] = settings.value(QSL("NotificationsGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::Notifications] = settings.value(QSL("NotificationsDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::Geolocation] = settings.value(QSL("GeolocationGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::Geolocation] = settings.value(QSL("GeolocationDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaAudioCapture] = settings.value(QSL("MediaAudioCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaAudioCapture] = settings.value(QSL("MediaAudioCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaVideoCapture] = settings.value(QSL("MediaVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaVideoCapture] = settings.value(QSL("MediaVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MediaAudioVideoCapture] = settings.value(QSL("MediaAudioVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MediaAudioVideoCapture] = settings.value(QSL("MediaAudioVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::MouseLock] = settings.value(QSL("MouseLockGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::MouseLock] = settings.value(QSL("MouseLockDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::DesktopVideoCapture] = settings.value(QSL("DesktopVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::DesktopVideoCapture] = settings.value(QSL("DesktopVideoCaptureDenied"), QStringList()).toStringList();
m_granted[QWebEnginePage::DesktopAudioVideoCapture] = settings.value(QSL("DesktopAudioVideoCaptureGranted"), QStringList()).toStringList();
m_denied[QWebEnginePage::DesktopAudioVideoCapture] = settings.value(QSL("DesktopAudioVideoCaptureDenied"), QStringList()).toStringList();
settings.endGroup();
}
void HTML5PermissionsManager::saveSettings()
{
Settings settings;
settings.beginGroup(QSL("HTML5Notifications"));
settings.setValue(QSL("NotificationsGranted"), m_granted[QWebEnginePage::Notifications]);
settings.setValue(QSL("NotificationsDenied"), m_denied[QWebEnginePage::Notifications]);
settings.setValue(QSL("GeolocationGranted"), m_granted[QWebEnginePage::Geolocation]);
settings.setValue(QSL("GeolocationDenied"), m_denied[QWebEnginePage::Geolocation]);
settings.setValue(QSL("MediaAudioCaptureGranted"), m_granted[QWebEnginePage::MediaAudioCapture]);
settings.setValue(QSL("MediaAudioCaptureDenied"), m_denied[QWebEnginePage::MediaAudioCapture]);
settings.setValue(QSL("MediaVideoCaptureGranted"), m_granted[QWebEnginePage::MediaVideoCapture]);
settings.setValue(QSL("MediaVideoCaptureDenied"), m_denied[QWebEnginePage::MediaVideoCapture]);
settings.setValue(QSL("MediaAudioVideoCaptureGranted"), m_granted[QWebEnginePage::MediaAudioVideoCapture]);
settings.setValue(QSL("MediaAudioVideoCaptureDenied"), m_denied[QWebEnginePage::MediaAudioVideoCapture]);
settings.setValue(QSL("MouseLockGranted"), m_granted[QWebEnginePage::MouseLock]);
settings.setValue(QSL("MouseLockDenied"), m_denied[QWebEnginePage::MouseLock]);
settings.setValue(QSL("DesktopVideoCaptureGranted"), m_granted[QWebEnginePage::DesktopVideoCapture]);
settings.setValue(QSL("DesktopVideoCaptureDenied"), m_denied[QWebEnginePage::DesktopVideoCapture]);
settings.setValue(QSL("DesktopAudioVideoCaptureGranted"), m_granted[QWebEnginePage::DesktopAudioVideoCapture]);
settings.setValue(QSL("DesktopAudioVideoCaptureDenied"), m_denied[QWebEnginePage::DesktopAudioVideoCapture]);
settings.endGroup();
} }

View File

@ -35,14 +35,6 @@ public:
void requestPermissions(WebPage* page, const QUrl &origin, const QWebEnginePage::Feature &feature); void requestPermissions(WebPage* page, const QUrl &origin, const QWebEnginePage::Feature &feature);
void rememberPermissions(const QUrl &origin, const QWebEnginePage::Feature &feature, void rememberPermissions(const QUrl &origin, const QWebEnginePage::Feature &feature,
const QWebEnginePage::PermissionPolicy &policy); const QWebEnginePage::PermissionPolicy &policy);
void loadSettings();
private:
void saveSettings();
QHash<QWebEnginePage::Feature, QStringList> m_granted;
QHash<QWebEnginePage::Feature, QStringList> m_denied;
}; };
#endif // HTML5PERMISSIONSMANAGER_H #endif // HTML5PERMISSIONSMANAGER_H

View File

@ -58,6 +58,11 @@ QVariant SqlQueryJob::lastInsertId() const
return m_lastInsertId; return m_lastInsertId;
} }
int SqlQueryJob::numRowsAffected() const
{
return m_numRowsAffected;
}
QVector<QSqlRecord> SqlQueryJob::records() const QVector<QSqlRecord> SqlQueryJob::records() const
{ {
return m_records; return m_records;
@ -68,6 +73,7 @@ void SqlQueryJob::start()
struct Result { struct Result {
QSqlError error; QSqlError error;
QVariant lastInsertId; QVariant lastInsertId;
int numRowsAffected;
QVector<QSqlRecord> records; QVector<QSqlRecord> records;
}; };
@ -82,6 +88,7 @@ void SqlQueryJob::start()
const auto result = watcher->result(); const auto result = watcher->result();
m_error = result.error; m_error = result.error;
m_lastInsertId = result.lastInsertId; m_lastInsertId = result.lastInsertId;
m_numRowsAffected = result.numRowsAffected;
m_records = result.records; m_records = result.records;
Q_EMIT finished(this); Q_EMIT finished(this);
}); });
@ -96,6 +103,7 @@ void SqlQueryJob::start()
Result res; Result res;
res.error = q.lastError(); res.error = q.lastError();
res.lastInsertId = q.lastInsertId(); res.lastInsertId = q.lastInsertId();
res.numRowsAffected = q.numRowsAffected();
while (q.next()) { while (q.next()) {
res.records.append(q.record()); res.records.append(q.record());
} }

View File

@ -37,6 +37,7 @@ public:
QSqlError error() const; QSqlError error() const;
QVariant lastInsertId() const; QVariant lastInsertId() const;
int numRowsAffected() const;
QVector<QSqlRecord> records() const; QVector<QSqlRecord> records() const;
void start(); void start();
@ -49,6 +50,7 @@ private:
QVector<QVariant> m_boundValues; QVector<QVariant> m_boundValues;
QSqlError m_error; QSqlError m_error;
QVariant m_lastInsertId; QVariant m_lastInsertId;
int m_numRowsAffected;
QVector<QSqlRecord> m_records; QVector<QSqlRecord> m_records;
}; };

View File

@ -33,6 +33,7 @@
#include "delayedfilewatcher.h" #include "delayedfilewatcher.h"
#include "searchenginesmanager.h" #include "searchenginesmanager.h"
#include "html5permissions/html5permissionsmanager.h" #include "html5permissions/html5permissionsmanager.h"
#include "sitesettingsmanager.h"
#include "javascript/externaljsobject.h" #include "javascript/externaljsobject.h"
#include "tabwidget.h" #include "tabwidget.h"
#include "networkmanager.h" #include "networkmanager.h"
@ -451,8 +452,35 @@ bool WebPage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::Navigatio
if (result) { if (result) {
if (isMainFrame) { if (isMainFrame) {
const bool isWeb = url.scheme() == QL1S("http") || url.scheme() == QL1S("https") || url.scheme() == QL1S("file"); const bool isWeb = url.scheme() == QL1S("http") || url.scheme() == QL1S("https") || url.scheme() == QL1S("file");
const bool globalJsEnabled = mApp->webSettings()->testAttribute(QWebEngineSettings::JavascriptEnabled);
settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, isWeb ? globalJsEnabled : true); if (isWeb) {
auto webAttributes = mApp->siteSettingsManager()->getWebAttributes(url);
if (!webAttributes.empty()) {
for (auto it = webAttributes.begin(); it != webAttributes.end(); ++it) {
settings()->setAttribute(it.key(), it.value());
}
}
else {
auto const webAttributes = mApp->siteSettingsManager()->getSupportedAttribute();
for (auto attribute : webAttributes) {
settings()->setAttribute(attribute, mApp->webSettings()->testAttribute(attribute));
}
}
}
else {
settings()->setAttribute(QWebEngineSettings::AutoLoadImages, true);
settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true);
settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste, false);
settings()->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, false);
settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, mApp->webSettings()->testAttribute(QWebEngineSettings::FullScreenSupportEnabled));
settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, false);
settings()->setAttribute(QWebEngineSettings::AllowGeolocationOnInsecureOrigins, false);
settings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, mApp->webSettings()->testAttribute(QWebEngineSettings::PlaybackRequiresUserGesture));
settings()->setAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly, false);
}
} }
Q_EMIT navigationRequestAccepted(url, type, isMainFrame); Q_EMIT navigationRequestAccepted(url, type, isMainFrame);
} }

View File

@ -23,4 +23,5 @@ endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(TestPlugin) add_subdirectory(TestPlugin)
add_subdirectory(SiteSettingsView)
endif() endif()

View File

@ -131,6 +131,8 @@ set(GENERATED_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/menu_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/menu_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/action_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/action_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/urlinterceptor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/urlinterceptor_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/sitesettingsmanager_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/sitesettingsmanager_sitesettings_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/extensionschemehandler_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/extensionschemehandler_wrapper.cpp
) )
set(GENERATED_SOURCES_DEPENDENCIES set(GENERATED_SOURCES_DEPENDENCIES

View File

@ -89,6 +89,9 @@
#include "sidebar.h" #include "sidebar.h"
#include "sidebarinterface.h" #include "sidebarinterface.h"
// siteSettings
#include "sitesettingsmanager.h"
// tabwidget // tabwidget
#include "combotabbar.h" #include "combotabbar.h"
#include "tabbar.h" #include "tabbar.h"

View File

@ -162,6 +162,12 @@
</modify-function> </modify-function>
</object-type> </object-type>
<object-type name="SiteSettingsManager">
<enum-type name="Permission"/>
<enum-type name="PageOptions"/>
<value-type name="SiteSettings"/>
</object-type>
<object-type name="ComboTabBar"> <object-type name="ComboTabBar">
<enum-type name="SizeType"/> <enum-type name="SizeType"/>
<enum-type name="DropIndicatorPosition"/> <enum-type name="DropIndicatorPosition"/>

View File

@ -0,0 +1,14 @@
set( SiteSettingsView_SRCS
sitesettingsview_controller.cpp
sitesettingsview_plugin.cpp
sitesettingsview_widget.cpp
sitesettingsview_controller.h
sitesettingsview_plugin.h
sitesettingsview_widget.h
)
ecm_create_qm_loader( SiteSettingsView_SRCS falkon_sitesettingsview_qt )
add_library(SiteSettingsView MODULE ${SiteSettingsView_SRCS} ${RSCS})
install(TARGETS SiteSettingsView DESTINATION ${FALKON_INSTALL_PLUGINDIR})
target_link_libraries(SiteSettingsView FalkonPrivate)

View File

@ -0,0 +1,2 @@
#! /bin/sh
$EXTRACT_TR_STRINGS `find . -name '*.cpp' -o -name '*.h' -o -name '*.ui'` -o $podir/falkon_sitesettingsview_qt.pot

View File

@ -0,0 +1,9 @@
{
"Comment": "Display configuration of configurable features for current website in sidebar.",
"Icon": "configure",
"Name": "Site Settings View",
"X-Falkon-Author": "Juraj Oravec",
"X-Falkon-Email": "jurajoravec@mailo.com",
"X-Falkon-Settings": "false",
"X-Falkon-Version": "0.1.0"
}

View File

@ -0,0 +1,80 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "sitesettingsview_controller.h"
#include "sitesettingsview_widget.h"
#include "sitesettingsmanager.h"
#include "mainapplication.h"
#include "webpage.h"
#include "webview.h"
#include <QAction>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTreeWidget>
SiteSettingsView_Controller::SiteSettingsView_Controller(QObject* parent)
: SideBarInterface(parent)
{
}
QString SiteSettingsView_Controller::title() const
{
return tr("Site Settings");
}
QAction* SiteSettingsView_Controller::createMenuAction()
{
// The action must be parented to some object from plugin, otherwise
// there may be a crash when unloading the plugin.
auto* act = new QAction(tr("Site Settings View"), this);
act->setCheckable(true);
return act;
}
QWidget* SiteSettingsView_Controller::createSideBarWidget(BrowserWindow* mainWindow)
{
auto *widget = new SiteSettingsView_Widget(mainWindow);
m_widgets[mainWindow] = widget;
return widget;
}
void SiteSettingsView_Controller::webPageCreated(WebPage* page)
{
connect(page, &WebPage::loadFinished, this, [=]() {
QHash<BrowserWindow*, QPointer<SiteSettingsView_Widget>>::iterator it;
for (it = m_widgets.begin(); it != m_widgets.end(); ++it) {
it.value()->loadFinished(page);
}
});
connect(page->view(), &WebView::zoomLevelChanged, this, [=](){
QHash<BrowserWindow*, QPointer<SiteSettingsView_Widget>>::iterator it;
for (it = m_widgets.begin(); it != m_widgets.end(); ++it) {
it.value()->loadFinished(page);
}
});
}
void SiteSettingsView_Controller::mainWindowDeleted(BrowserWindow* window)
{
m_widgets.remove(window);
}

View File

@ -0,0 +1,47 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef SITESETTINGSVIEW_CONTROLLER_H
#define SITESETTINGSVIEW_CONTROLLER_H
#include "sidebarinterface.h"
class WebPage;
class SiteSettingsView;
class SiteSettingsView_Widget;
class SiteSettingsView_Controller : public SideBarInterface
{
Q_OBJECT
public:
explicit SiteSettingsView_Controller(QObject* parent = nullptr);
QString title() const override;
QAction* createMenuAction() override;
QWidget* createSideBarWidget(BrowserWindow* mainWindow) override;
public Q_SLOTS:
void webPageCreated(WebPage* page);
void mainWindowDeleted(BrowserWindow* window);
private:
QHash<BrowserWindow*, QPointer<SiteSettingsView_Widget>> m_widgets;
};
#endif // SITESETTINGSVIEW_CONTROLLER_H

View File

@ -0,0 +1,66 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "sitesettingsview_plugin.h"
#include "sitesettingsview_controller.h"
#include "browserwindow.h"
#include "webview.h"
#include "pluginproxy.h"
#include "mainapplication.h"
#include "sidebar.h"
#include "webhittestresult.h"
#include "../config.h"
#include <QMenu>
#include <QPushButton>
SiteSettingsView::SiteSettingsView()
: QObject()
, m_view(nullptr)
{
}
void SiteSettingsView::init(InitState state, const QString &settingsPath)
{
Q_UNUSED(settingsPath)
// State can be either StartupInitState or LateInitState, and it
// indicates when the plugin have been loaded.
// Currently, it can be from preferences, or automatically at startup.
// Plugins are loaded before first BrowserWindow is created.
Q_UNUSED(state)
// Adding new sidebar into application
m_sideBar = new SiteSettingsView_Controller(this);
SideBarManager::addSidebar(QSL("sitesettingsview-sidebar"), m_sideBar);
connect(mApp->plugins(), &PluginProxy::webPageCreated, m_sideBar, &SiteSettingsView_Controller::webPageCreated);
connect(mApp->plugins(), &PluginProxy::mainWindowDeleted, m_sideBar, &SiteSettingsView_Controller::mainWindowDeleted);
}
void SiteSettingsView::unload()
{
// Removing sidebar from application
SideBarManager::removeSidebar(m_sideBar);
delete m_sideBar;
}
bool SiteSettingsView::testPlugin()
{
return (QString::fromLatin1(Qz::VERSION) == QLatin1String(FALKON_VERSION));
}

View File

@ -1,6 +1,6 @@
/* ============================================================ /* ============================================================
* Falkon - Qt web browser * Falkon - Qt web browser
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com> * Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -15,44 +15,37 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */ * ============================================================ */
#ifndef HTML5PERMISSIONSDIALOG_H
#define HTML5PERMISSIONSDIALOG_H
#include <QDialog> #ifndef SITESETTINGSVIEW_PLUGIN_H
#include <QStringList> #define SITESETTINGSVIEW_PLUGIN_H
#include <QWebEnginePage>
namespace Ui #include "plugininterface.h"
{
class HTML5PermissionsDialog;
}
class HTML5PermissionsDialog : public QDialog #include <QLabel>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QPointer>
class SiteSettingsView_Controller;
class SiteSettingsView : public QObject, public PluginInterface
{ {
Q_OBJECT Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "Falkon.Browser.plugin.SiteSettingsView" FILE "sitesettingsview.json")
public: public:
explicit HTML5PermissionsDialog(QWidget* parent = nullptr); explicit SiteSettingsView();
~HTML5PermissionsDialog();
void showFeaturePermissions(QWebEnginePage::Feature feature); void init(InitState state, const QString &settingsPath) override;
void unload() override;
bool testPlugin() override;
private Q_SLOTS: private Q_SLOTS:
void removeEntry();
void featureIndexChanged();
void saveSettings();
private: private:
enum Role { Allow, Deny }; WebView* m_view;
SiteSettingsView_Controller *m_sideBar = nullptr;
void loadSettings();
QWebEnginePage::Feature currentFeature() const;
Ui::HTML5PermissionsDialog* ui;
QHash<QWebEnginePage::Feature, QStringList> m_granted;
QHash<QWebEnginePage::Feature, QStringList> m_denied;
}; };
#endif // HTML5PERMISSIONSDIALOG_H #endif // SITESETTINGSVIEW_PLUGIN_H

View File

@ -0,0 +1,276 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "sitesettingsview_widget.h"
#include "tabwidget.h"
#include "browserwindow.h"
#include "mainapplication.h"
#include "sitesettingsmanager.h"
#include "tabbedwebview.h"
#include "webpage.h"
#include "qzsettings.h"
#include <QTreeWidget>
#include <QHeaderView>
#include <QWebEngineProfile>
#include <QSpacerItem>
SiteSettingsView_Widget::SiteSettingsView_Widget(BrowserWindow* window)
{
m_window = window;
m_brushGreen = QBrush(QColorConstants::Green);
m_brushYellow = QBrush(QColorConstants::Yellow);
m_brushOrange = QBrush(QColorConstants::Svg::orange);
m_brushRed = QBrush(QColorConstants::Red);
m_brushBlue = QBrush(QColorConstants::Blue);
m_availableOptions = {
SiteSettingsManager::poAllowCookies,
SiteSettingsManager::poZoomLevel
};
QSpacerItem *horizontalSpacer_1 = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
QSpacerItem *horizontalSpacer_2 = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
auto *layoutTitle = new QHBoxLayout();
auto *modeNameLabel = new QLabel(this);
QString nameLabelText = QSL("<b>%1</b> <font color='%2'>%3</font>").arg(tr("Mode:"));
if (mApp->isPrivate()) {
modeNameLabel->setText(nameLabelText.arg(QSL("red"), tr("Private")));
}
else {
modeNameLabel->setText(nameLabelText.arg(QSL("lightgreen"), tr("Normal")));
}
auto *isWebLabel = new QLabel(QSL("<b>%1</b> ").arg(tr("isWeb:")), this);
m_isWebValue = new QLabel(this);
auto *buttonRefresh = new QToolButton(this);
buttonRefresh->setIcon(QIcon::fromTheme(QSL("view-refresh")));
buttonRefresh->setToolTip(tr("Refresh"));
layoutTitle->addWidget(modeNameLabel);
layoutTitle->addItem(horizontalSpacer_1);
layoutTitle->addWidget(isWebLabel);
layoutTitle->addWidget(m_isWebValue);
layoutTitle->addItem(horizontalSpacer_2);
layoutTitle->addWidget(buttonRefresh);
m_attributes = new QTreeWidget(this);
m_attributes->setColumnCount(4);
m_attributes->setHeaderLabels({tr("Real"), tr("Local"), tr("Default"), tr("Attributes")});
m_attributes->setSortingEnabled(true);
m_attributes->sortByColumn(3, Qt::AscendingOrder);
m_attributes->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_attributes->header()->setSectionsMovable(false);
m_attributes->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
m_attributes->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto attributes = mApp->siteSettingsManager()->getSupportedAttribute();
for (auto &attr : attributes) {
auto *item = new QTreeWidgetItem(m_attributes, {QSL(""), QSL(""), QSL(""), mApp->siteSettingsManager()->getOptionName(attr)});
item->setToolTip(3, mApp->siteSettingsManager()->getOptionName(attr));
m_attributeItems.insert(attr, item);
}
m_features = new QTreeWidget(this);
m_features->setColumnCount(3);
m_features->setHeaderLabels({tr("Local"), tr("Default"), tr("Feature")});
m_features->setSortingEnabled(true);
m_features->sortByColumn(2, Qt::AscendingOrder);
m_features->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_features->header()->setSectionsMovable(false);
m_features->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
m_features->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto features = mApp->siteSettingsManager()->getSupportedFeatures();
for (auto &feature : features) {
auto *item = new QTreeWidgetItem(m_features, {QSL(""), QSL(""), mApp->siteSettingsManager()->getOptionName(feature)});
item->setToolTip(2, mApp->siteSettingsManager()->getOptionName(feature));
m_featureItems.insert(feature, item);
}
m_options = new QTreeWidget(this);
m_options->setColumnCount(3);
m_options->setHeaderLabels({tr("Real"), tr("Local"), tr("Default"), tr("Option")});
m_options->setSortingEnabled(true);
m_options->sortByColumn(3, Qt::AscendingOrder);
m_options->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_options->header()->setSectionsMovable(false);
m_options->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
m_options->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
for (auto &option : m_availableOptions) {
auto *item = new QTreeWidgetItem(m_options, {QSL(""), QSL(""), QSL(""), mApp->siteSettingsManager()->getOptionName(option)});
item->setToolTip(3, mApp->siteSettingsManager()->getOptionName(option));
m_optionsItems.insert(option, item);
}
QSpacerItem *verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
auto *l = new QVBoxLayout(this);
l->addItem(layoutTitle);
l->addWidget(m_attributes);
l->addWidget(m_features);
l->addWidget(m_options);
l->addItem(verticalSpacer);
this->setLayout(l);
connect(m_window->tabWidget(), &TabWidget::currentChanged, this, &SiteSettingsView_Widget::updateData);
connect(buttonRefresh, &QToolButton::clicked, this, &SiteSettingsView_Widget::updateData);
updateData();
}
void SiteSettingsView_Widget::updateData(int index)
{
Q_UNUSED(index)
auto *tab = m_window->tabWidget()->webTab();
if (tab == nullptr) {
return;
}
auto url = tab->url();
/* This condition is copied from webpage.cpp function acceptNavigationRequest()
* Falkon has hardcoded properties / attributes for non Web pages*/
const bool isWeb = url.scheme() == QL1S("http") || url.scheme() == QL1S("https") || url.scheme() == QL1S("file");
const auto siteSettings = mApp->siteSettingsManager()->getSiteSettings(url);
if (isWeb) {
m_isWebValue->setText(QSL("<font color='lightgreen'>%1</font>").arg(tr("True")));
}
else {
m_isWebValue->setText(QSL("<font color='red'>%1</font>").arg(tr("False")));
}
QHash<QWebEngineSettings::WebAttribute, QTreeWidgetItem*>::iterator it_attr;
for (it_attr = m_attributeItems.begin(); it_attr != m_attributeItems.end(); ++it_attr) {
auto attr = it_attr.key();
auto attrReal = tab->webView()->page()->settings()->testAttribute(attr) ? SiteSettingsManager::Allow : SiteSettingsManager::Deny;
auto attrDefault = mApp->webProfile()->settings()->testAttribute(attr) ? SiteSettingsManager::Allow : SiteSettingsManager::Deny;
auto attrLocal = SiteSettingsManager::Default;
if (!siteSettings.attributes.empty() && siteSettings.attributes.contains(attr)) {
attrLocal = siteSettings.attributes[attr];
}
auto *item = it_attr.value();
item->setText(0, mApp->siteSettingsManager()->getPermissionName(attrReal));
item->setForeground(0, permissionColor(attrReal));
item->setText(1, mApp->siteSettingsManager()->getPermissionName(attrLocal));
item->setForeground(1, permissionColor(attrLocal));
item->setText(2, mApp->siteSettingsManager()->getPermissionName(attrDefault));
item->setForeground(2, permissionColor(attrDefault));
}
QHash<QWebEnginePage::Feature, QTreeWidgetItem*>::iterator it_ftr;
for (it_ftr = m_featureItems.begin(); it_ftr != m_featureItems.end(); ++it_ftr) {
auto ftr = it_ftr.key();
auto ftrDefault = mApp->siteSettingsManager()->getDefaultPermission(ftr);
auto ftrLocal = siteSettings.features[ftr];
auto *item = it_ftr.value();
item->setText(0, mApp->siteSettingsManager()->getPermissionName(ftrLocal));
item->setForeground(0, permissionColor(ftrLocal));
item->setText(1, mApp->siteSettingsManager()->getPermissionName(ftrDefault));
item->setForeground(1, permissionColor(ftrDefault));
}
QHash<SiteSettingsManager::PageOptions, QTreeWidgetItem*>::iterator it_opt;
for (it_opt = m_optionsItems.begin(); it_opt != m_optionsItems.end(); ++it_opt) {
QString optRealText, optLocalText, optDefaultText;
QBrush optRealColor, optLocalColor, optDefaultColor;
const auto option = it_opt.key();
auto *item = it_opt.value();
switch (option) {
case SiteSettingsManager::poAllowCookies: {
SiteSettingsManager::Permission permission;
optLocalText = mApp->siteSettingsManager()->getPermissionName(siteSettings.AllowCookies);
optLocalColor = permissionColor(siteSettings.AllowCookies);
permission = mApp->siteSettingsManager()->getDefaultPermission(option);
optDefaultText = mApp->siteSettingsManager()->getPermissionName(permission);
optDefaultColor = permissionColor(permission);
}
break;
case SiteSettingsManager::poZoomLevel: {
auto zoomLevels = WebView::zoomLevels();
const int realZoomLevel = tab->webView()->zoomLevel();
const int defualZoomLevel = qzSettings->defaultZoomLevel;
const int storedZoomLevel = siteSettings.ZoomLevel;
optRealText = tr("%1 (%2%)").arg(realZoomLevel).arg(zoomLevels[realZoomLevel]);
optRealColor = m_brushGreen;
if (storedZoomLevel == -1) {
optLocalText = tr("Default");
optLocalColor = m_brushYellow;
}
else {
optLocalText = tr("%1 (%2%)").arg(storedZoomLevel).arg(zoomLevels[storedZoomLevel]);
optLocalColor = m_brushGreen;
}
optDefaultText = tr("%1 (%2%)").arg(defualZoomLevel).arg(zoomLevels[defualZoomLevel]);
optDefaultColor = m_brushGreen;
}
break;
default:
qDebug() << "Unknown option: " << option;
continue;
}
item->setText(0, optRealText);
item->setForeground(0, optRealColor);
item->setText(1, optLocalText);
item->setForeground(1, optLocalColor);
item->setText(2, optDefaultText);
item->setForeground(2, optDefaultColor);
}
}
QBrush SiteSettingsView_Widget::permissionColor(SiteSettingsManager::Permission permission)
{
switch (permission) {
case SiteSettingsManager::Default:
return m_brushYellow;
case SiteSettingsManager::Allow:
return m_brushGreen;
case SiteSettingsManager::Deny:
return m_brushRed;
case SiteSettingsManager::Ask:
return m_brushOrange;
default:
return m_brushBlue;
}
}
void SiteSettingsView_Widget::loadFinished(WebPage* page)
{
auto *tab = m_window->tabWidget()->webTab();
if (tab == nullptr) {
return;
}
if (page == tab->webView()->page()) {
updateData();
}
}

View File

@ -0,0 +1,66 @@
/* ============================================================
* Falkon - Qt web browser
* Copyright (C) 2024 Juraj Oravec <jurajoravec@mailo.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef SITESETTINGSVIEW_WIDGET_H
#define SITESETTINGSVIEW_WIDGET_H
#include "sitesettingsview_plugin.h"
#include "sitesettingsmanager.h"
#include <QWidget>
#include <QWebEngineSettings>
class QTreeWidget;
class QTreeWidgetItem;
class BrowserWindow;
class SiteSettingsView_Widget : public QWidget
{
Q_OBJECT
public:
explicit SiteSettingsView_Widget(BrowserWindow *window);
void loadFinished(WebPage* page);
private Q_SLOTS:
void updateData(int index = 0);
private:
QTreeWidget *m_attributes;
QTreeWidget *m_features;
QTreeWidget *m_options;
BrowserWindow *m_window;
QBrush m_brushGreen;
QBrush m_brushYellow;
QBrush m_brushOrange;
QBrush m_brushRed;
QBrush m_brushBlue;
QLabel *m_isWebValue;
QList<SiteSettingsManager::PageOptions> m_availableOptions;
QHash<QWebEngineSettings::WebAttribute, QTreeWidgetItem*> m_attributeItems;
QHash<QWebEnginePage::Feature, QTreeWidgetItem*> m_featureItems;
QHash<SiteSettingsManager::PageOptions, QTreeWidgetItem*> m_optionsItems;
QBrush permissionColor(SiteSettingsManager::Permission permission);
};
#endif /* SITESETTINGSVIEW_WIDGET_H */

View File

@ -21,6 +21,7 @@
#include "tabbedwebview.h" #include "tabbedwebview.h"
#include "webpage.h" #include "webpage.h"
#include "jsoptions.h" #include "jsoptions.h"
#include "mainapplication.h"
#include <QGraphicsColorizeEffect> #include <QGraphicsColorizeEffect>
#include <QWebEngineSettings> #include <QWebEngineSettings>