From 205018775ce1c66b349d6b5a20abcb08e5ed19f6 Mon Sep 17 00:00:00 2001 From: Juraj Oravec Date: Fri, 7 Apr 2023 00:06:15 +0200 Subject: [PATCH] Add support for custom url schemes BUG: 434099 FIXED_IN: 23.08.0 Signed-off-by: Juraj Oravec --- src/lib/CMakeLists.txt | 3 + src/lib/app/mainapplication.cpp | 15 + src/lib/app/mainapplication.h | 2 + src/lib/other/qzsettings.cpp | 2 + src/lib/other/qzsettings.h | 3 + src/lib/preferences/preferences.cpp | 8 + src/lib/preferences/preferences.h | 1 + src/lib/preferences/preferences.ui | 339 ++++++++++-------- src/lib/preferences/schememanager.cpp | 143 ++++++++ src/lib/preferences/schememanager.h | 52 +++ src/lib/preferences/schememanager.ui | 191 ++++++++++ .../kdeframeworksintegrationplugin.cpp | 29 +- 12 files changed, 641 insertions(+), 147 deletions(-) create mode 100644 src/lib/preferences/schememanager.cpp create mode 100644 src/lib/preferences/schememanager.h create mode 100644 src/lib/preferences/schememanager.ui diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 52cc0393b..806800aeb 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -207,6 +207,7 @@ set(SRCS ${SRCS} preferences/pluginlistdelegate.cpp preferences/pluginsmanager.cpp preferences/preferences.cpp + preferences/schememanager.cpp preferences/thememanager.cpp preferences/useragentdialog.cpp session/recoveryjsobject.cpp @@ -436,6 +437,7 @@ set(SRCS ${SRCS} preferences/pluginlistdelegate.h preferences/pluginsmanager.h preferences/preferences.h + preferences/schememanager.h preferences/thememanager.h preferences/useragentdialog.h session/recoveryjsobject.h @@ -549,6 +551,7 @@ qt_wrap_ui(SRCS preferences/jsoptions.ui preferences/pluginslist.ui preferences/preferences.ui + preferences/schememanager.ui preferences/thememanager.ui preferences/useragentdialog.ui session/sessionmanagerdialog.ui diff --git a/src/lib/app/mainapplication.cpp b/src/lib/app/mainapplication.cpp index dcf27cc37..53e6cb062 100644 --- a/src/lib/app/mainapplication.cpp +++ b/src/lib/app/mainapplication.cpp @@ -69,6 +69,7 @@ #include #include +#include #ifdef Q_OS_WIN #include @@ -293,6 +294,7 @@ MainApplication::MainApplication(int &argc, char** argv) } NetworkManager::registerSchemes(); + registerAllowedSchemes(); m_webProfile = isPrivate() ? new QWebEngineProfile() : QWebEngineProfile::defaultProfile(); connect(m_webProfile, &QWebEngineProfile::downloadRequested, this, &MainApplication::downloadRequested); @@ -1116,6 +1118,19 @@ void MainApplication::checkOptimizeDatabase() settings.endGroup(); } +void MainApplication::registerAllowedSchemes() +{ + for (const QString &schemeName : qAsConst(qzSettings->allowedSchemes)) { + if (qzSettings->blockedSchemes.contains(schemeName)) { + continue; + } + QWebEngineUrlScheme scheme(schemeName.toUtf8()); + scheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::ContentSecurityPolicyIgnored); + scheme.setSyntax(QWebEngineUrlScheme::Syntax::Path); + QWebEngineUrlScheme::registerScheme(scheme); + } +} + void MainApplication::setupUserScripts() { // WebChannel for SafeJsWorld diff --git a/src/lib/app/mainapplication.h b/src/lib/app/mainapplication.h index 0b0b5d20f..5bffe26b2 100644 --- a/src/lib/app/mainapplication.h +++ b/src/lib/app/mainapplication.h @@ -164,6 +164,8 @@ private: void checkDefaultWebBrowser(); void checkOptimizeDatabase(); + void registerAllowedSchemes(); + bool m_isPrivate; bool m_isPortable; bool m_isClosing; diff --git a/src/lib/other/qzsettings.cpp b/src/lib/other/qzsettings.cpp index 6441d13a1..61a70cfa5 100644 --- a/src/lib/other/qzsettings.cpp +++ b/src/lib/other/qzsettings.cpp @@ -51,6 +51,8 @@ void QzSettings::loadSettings() loadTabsOnActivation = settings.value("LoadTabsOnActivation", true).toBool(); autoOpenProtocols = settings.value("AutomaticallyOpenProtocols", QStringList()).toStringList(); blockedProtocols = settings.value("BlockOpeningProtocols", QStringList()).toStringList(); + allowedSchemes = settings.value("AllowedSchemes", QStringList()).toStringList(); + blockedSchemes = settings.value("BlockedSchemes", QStringList()).toStringList(); settings.endGroup(); settings.beginGroup("Browser-Tabs-Settings"); diff --git a/src/lib/other/qzsettings.h b/src/lib/other/qzsettings.h index f517182c4..aaeac786b 100644 --- a/src/lib/other/qzsettings.h +++ b/src/lib/other/qzsettings.h @@ -56,6 +56,9 @@ public: QStringList autoOpenProtocols; QStringList blockedProtocols; + QStringList allowedSchemes; + QStringList blockedSchemes; + // Browser-Tabs-Settings Qz::NewTabPositionFlags newTabPosition; bool tabsOnTop; diff --git a/src/lib/preferences/preferences.cpp b/src/lib/preferences/preferences.cpp index f41d25f73..0e8771724 100644 --- a/src/lib/preferences/preferences.cpp +++ b/src/lib/preferences/preferences.cpp @@ -48,6 +48,7 @@ #include "searchenginesdialog.h" #include "webscrollbarmanager.h" #include "protocolhandlerdialog.h" +#include "schememanager.h" #include "../config.h" #include @@ -522,6 +523,7 @@ Preferences::Preferences(BrowserWindow* window) connect(ui->searchEngines, &QAbstractButton::clicked, this, &Preferences::openSearchEnginesManager); connect(ui->certificateManager, &QAbstractButton::clicked, this, &Preferences::openCertificateManager); connect(ui->protocolHandlers, &QAbstractButton::clicked, this, &Preferences::openProtocolHandlersManager); + connect(ui->customSchemes, &QAbstractButton::clicked, this, &Preferences::openSchemesManager); connect(ui->listWidget, &QListWidget::currentItemChanged, this, &Preferences::showStackedPage); ui->listWidget->itemAt(5, 5)->setSelected(true); @@ -754,6 +756,12 @@ void Preferences::openProtocolHandlersManager() dialog->open(); } +void Preferences::openSchemesManager() +{ + auto *dialog = new SchemeManager(this); + dialog->open(); +} + void Preferences::showAcceptLanguage() { auto* dialog = new AcceptLanguage(this); diff --git a/src/lib/preferences/preferences.h b/src/lib/preferences/preferences.h index 03d82a0d7..3855a054a 100644 --- a/src/lib/preferences/preferences.h +++ b/src/lib/preferences/preferences.h @@ -66,6 +66,7 @@ private Q_SLOTS: void openSearchEnginesManager(); void openCertificateManager(); void openProtocolHandlersManager(); + void openSchemesManager(); void searchFromAddressBarChanged(bool state); void saveHistoryChanged(bool state); diff --git a/src/lib/preferences/preferences.ui b/src/lib/preferences/preferences.ui index 4e326c88a..f31e83529 100644 --- a/src/lib/preferences/preferences.ui +++ b/src/lib/preferences/preferences.ui @@ -2474,120 +2474,6 @@ - - - - <b>Preferred language for web sites</b> - - - - - - - <b>Manage protocol handlers</b> - - - - - - - <b>Certificate manager</b> - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Certificate Exception Manager - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - User Agent Manager - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -2628,20 +2514,6 @@ - - - - <b>Manage search engines</b> - - - - - - - Style Sheet automatically loaded with all websites: - - - @@ -2682,26 +2554,33 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + <b>User Style Sheet</b> + + + + <b>Manage search engines</b> + + + + + + + + 75 + true + + + + Manage custom schemes + + + @@ -2742,6 +2621,53 @@ + + + + <b>Preferred language for web sites</b> + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Certificate Exception Manager + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -2749,7 +2675,54 @@ - + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + User Agent Manager + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Style Sheet automatically loaded with all websites: + + + + @@ -2779,6 +2752,86 @@ + + + + <b>Manage protocol handlers</b> + + + + + + + <b>Certificate manager</b> + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Custom Scheme Manager + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/lib/preferences/schememanager.cpp b/src/lib/preferences/schememanager.cpp new file mode 100644 index 000000000..af4aaaad7 --- /dev/null +++ b/src/lib/preferences/schememanager.cpp @@ -0,0 +1,143 @@ +/* ============================================================ + * Falkon - Qt web browser + * Copyright (C) 2023 Juraj Oravec + * + * 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 . + * ============================================================ */ + +#include "ui_schememanager.h" +#include "schememanager.h" +#include "qzsettings.h" + +#include +#include + +SchemeManager::SchemeManager(QWidget* parent) + : QDialog(parent) + , m_ui(new Ui::SchemeManager) +{ + setAttribute(Qt::WA_DeleteOnClose); + + m_ui->setupUi(this); + + reset(); + + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &SchemeManager::accept); + connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked, this, &SchemeManager::reset); + connect(m_ui->blockButton, &QAbstractButton::clicked, this, &SchemeManager::blockScheme); + connect(m_ui->allowedAddButton, &QAbstractButton::clicked, this, &SchemeManager::allowedAdd); + connect(m_ui->allowedRemoveButton, &QAbstractButton::clicked, this, &SchemeManager::allowedRemove); + connect(m_ui->blockedAddButton, &QAbstractButton::clicked, this, &SchemeManager::blockedAdd); + connect(m_ui->blockedRemoveButton, &QAbstractButton::clicked, this, &SchemeManager::blockedRemove); +} + +void SchemeManager::reset() +{ + Settings settings; + settings.beginGroup(QSL("Web-Browser-Settings")); + + m_ui->allowedList->clear(); + m_ui->allowedList->addItems(settings.value(QSL("AllowedSchemes"), QStringList()).toStringList()); + + m_ui->blockedList->clear(); + m_ui->blockedList->addItems(settings.value(QSL("BlockedSchemes"), QStringList()).toStringList()); + + settings.endGroup(); +} + +void SchemeManager::accept() +{ + QStringList list; + Settings settings; + settings.beginGroup(QSL("Web-Browser-Settings")); + + for (int i = 0; i < m_ui->allowedList->count(); ++i) { + list.append(m_ui->allowedList->item(i)->text().toLower()); + } + list.removeDuplicates(); + settings.setValue(QSL("AllowedSchemes"), list); + + list.clear(); + for (int i = 0; i < m_ui->blockedList->count(); ++i) { + list.append(m_ui->blockedList->item(i)->text().toLower()); + } + list.removeDuplicates(); + settings.setValue(QSL("BlockedSchemes"), list); + settings.endGroup(); + + QDialog::close(); +} + +void SchemeManager::allowedAdd() +{ + const QString scheme = QInputDialog::getText(this, tr("Add allowed scheme"), tr("Scheme:")); + + if (scheme.isEmpty()) { + return; + } + + if (m_ui->allowedList->findItems(scheme, Qt::MatchFixedString).isEmpty()) { + m_ui->allowedList->addItem(scheme); + } +} + +void SchemeManager::allowedRemove() +{ + int currentRow = m_ui->allowedList->currentRow(); + auto* item = m_ui->allowedList->item(currentRow); + + if ((item != nullptr) && (item->isSelected())) { + m_ui->allowedList->takeItem(m_ui->allowedList->currentRow()); + } +} + +void SchemeManager::blockScheme() +{ + int currentRow = m_ui->allowedList->currentRow(); + auto* item = m_ui->allowedList->item(currentRow); + + if ((item != nullptr) && (item->isSelected())) { + if (m_ui->blockedList->findItems(item->text(), Qt::MatchFixedString).isEmpty()) { + m_ui->blockedList->addItem(item->text()); + } + } +} + +void SchemeManager::blockedAdd() +{ + const QString scheme = QInputDialog::getText(this, tr("Add blocked scheme"), tr("Scheme:")); + + if (scheme.isEmpty()) { + return; + } + + if (m_ui->blockedList->findItems(scheme, Qt::MatchFixedString).isEmpty()) { + m_ui->blockedList->addItem(scheme); + } +} + +void SchemeManager::blockedRemove() +{ + int currentRow = m_ui->blockedList->currentRow(); + auto* item = m_ui->blockedList->item(currentRow); + + if ((item != nullptr) && (item->isSelected())) { + m_ui->blockedList->takeItem(m_ui->blockedList->currentRow()); + } +} + +SchemeManager::~SchemeManager() +{ + delete m_ui; +} diff --git a/src/lib/preferences/schememanager.h b/src/lib/preferences/schememanager.h new file mode 100644 index 000000000..fce784669 --- /dev/null +++ b/src/lib/preferences/schememanager.h @@ -0,0 +1,52 @@ +/* ============================================================ + * Falkon - Qt web browser + * Copyright (C) 2023 Juraj Oravec + * + * 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 . + * ============================================================ */ + +#ifndef SCHEMEMANAGER_H +#define SCHEMEMANAGER_H + +#include + +namespace Ui { +class SchemeManager; +} + +class SchemeManager : public QDialog +{ + Q_OBJECT + +public: + explicit SchemeManager(QWidget* parent = nullptr); + ~SchemeManager() override; + +public Q_SLOTS: + void accept() override; + +private Q_SLOTS: + void reset(); + void blockScheme(); + + void allowedAdd(); + void allowedRemove(); + void blockedAdd(); + void blockedRemove(); + +private: + Ui::SchemeManager *m_ui; +}; + +#endif // SCHEMEMANAGER_H diff --git a/src/lib/preferences/schememanager.ui b/src/lib/preferences/schememanager.ui new file mode 100644 index 000000000..b6bfaa864 --- /dev/null +++ b/src/lib/preferences/schememanager.ui @@ -0,0 +1,191 @@ + + + SchemeManager + + + + 0 + 0 + 490 + 499 + + + + Custom scheme manager + + + + + + + 75 + true + + + + Allowed schemes + + + + + + + **Note:** Allowed schemes can be added by extensions. + + + Qt::MarkdownText + + + + + + + + + true + + + + + + + + + Add + + + + + + + Remove + + + + + + + Block + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 75 + true + + + + Blocked schemes + + + + + + + + + true + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Changes will take effect after Falkon restart. + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset + + + + + + + allowedList + allowedAddButton + allowedRemoveButton + blockButton + blockedList + blockedAddButton + blockedRemoveButton + + + + + buttonBox + rejected() + SchemeManager + reject() + + + 302 + 475 + + + 404 + 413 + + + + + diff --git a/src/plugins/KDEFrameworksIntegration/kdeframeworksintegrationplugin.cpp b/src/plugins/KDEFrameworksIntegration/kdeframeworksintegrationplugin.cpp index 7c647903e..f10cec02a 100644 --- a/src/plugins/KDEFrameworksIntegration/kdeframeworksintegrationplugin.cpp +++ b/src/plugins/KDEFrameworksIntegration/kdeframeworksintegrationplugin.cpp @@ -29,6 +29,7 @@ #include "webview.h" #include "downloadkjob.h" #include "downloaditem.h" +#include "settings.h" #include #include @@ -37,6 +38,7 @@ #include #include +#include #include #include @@ -74,15 +76,34 @@ void KDEFrameworksIntegrationPlugin::init(InitState state, const QString &settin }); + QStringList newSchemes; const auto protocols = KProtocolInfo::protocols(); for (const QString &protocol : protocols) { if (WebPage::internalSchemes().contains(protocol)) { continue; } - auto *handler = new KIOSchemeHandler(protocol, this); - m_kioSchemeHandlers.append(handler); - mApp->webProfile()->installUrlSchemeHandler(protocol.toUtf8(), handler); - WebPage::addSupportedScheme(protocol); + if (!QWebEngineUrlScheme::schemeByName(protocol.toUtf8()).name().isEmpty()) { + auto *handler = new KIOSchemeHandler(protocol, this); + m_kioSchemeHandlers.append(handler); + mApp->webProfile()->installUrlSchemeHandler(protocol.toUtf8(), handler); + WebPage::addSupportedScheme(protocol); + } + else { + newSchemes.append(protocol); + qInfo() << QSL("KDEFrameworksIntegration: Custom scheme '%1' will be available after browser restart.").arg(protocol); + } + } + + if (!newSchemes.isEmpty()) { + Settings settings; + settings.beginGroup(QSL("Web-Browser-Settings")); + + QStringList allowedSchemes = settings.value(QSL("AllowedSchemes"), QStringList()).toStringList(); + allowedSchemes.append(newSchemes); + allowedSchemes.removeDuplicates(); + settings.setValue(QSL("AllowedSchemes"), allowedSchemes); + + settings.endGroup(); } m_sharePageMenu = new Purpose::Menu();