mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 10:46:35 +01:00
OcsSupport: Add initial support for downloading themes/extensions
This commit is contained in:
parent
13449605eb
commit
5e6f92f7bc
@ -88,6 +88,9 @@ endif()
|
|||||||
# Mandatory: OpenSSL
|
# Mandatory: OpenSSL
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
|
# Mandatory: KF5
|
||||||
|
find_package(KF5 REQUIRED COMPONENTS Archive)
|
||||||
|
|
||||||
# KF5I18n: Mandatory with downloaded translations (only for ki18n_install)
|
# KF5I18n: Mandatory with downloaded translations (only for ki18n_install)
|
||||||
if (EXISTS "${CMAKE_SOURCE_DIR}/po")
|
if (EXISTS "${CMAKE_SOURCE_DIR}/po")
|
||||||
find_package(KF5I18n REQUIRED)
|
find_package(KF5I18n REQUIRED)
|
||||||
|
@ -156,6 +156,7 @@ set(SRCS ${SRCS}
|
|||||||
plugins/pluginproxy.cpp
|
plugins/pluginproxy.cpp
|
||||||
plugins/plugins.cpp
|
plugins/plugins.cpp
|
||||||
plugins/speeddial.cpp
|
plugins/speeddial.cpp
|
||||||
|
plugins/ocssupport.cpp
|
||||||
plugins/qml/qmlpluginloader.cpp
|
plugins/qml/qmlpluginloader.cpp
|
||||||
plugins/qml/qmlplugin.cpp
|
plugins/qml/qmlplugin.cpp
|
||||||
plugins/qml/qmlplugins.cpp
|
plugins/qml/qmlplugins.cpp
|
||||||
@ -348,6 +349,7 @@ target_link_libraries(FalkonPrivate
|
|||||||
Qt5::PrintSupport
|
Qt5::PrintSupport
|
||||||
Qt5::QuickWidgets
|
Qt5::QuickWidgets
|
||||||
Qt5::WebChannel
|
Qt5::WebChannel
|
||||||
|
KF5::Archive
|
||||||
${OPENSSL_CRYPTO_LIBRARY}
|
${OPENSSL_CRYPTO_LIBRARY}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,6 +61,11 @@ bool DesktopNotificationsFactory::supportsNativeNotifications() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DesktopNotificationsFactory::showNotification(const QString &heading, const QString &text)
|
||||||
|
{
|
||||||
|
showNotification(QPixmap(), heading, text);
|
||||||
|
}
|
||||||
|
|
||||||
void DesktopNotificationsFactory::showNotification(const QPixmap &icon, const QString &heading, const QString &text)
|
void DesktopNotificationsFactory::showNotification(const QPixmap &icon, const QString &heading, const QString &text)
|
||||||
{
|
{
|
||||||
if (!m_enabled) {
|
if (!m_enabled) {
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
|
|
||||||
bool supportsNativeNotifications() const;
|
bool supportsNativeNotifications() const;
|
||||||
|
|
||||||
|
void showNotification(const QString &heading, const QString &text);
|
||||||
void showNotification(const QPixmap &icon, const QString &heading, const QString &text);
|
void showNotification(const QPixmap &icon, const QString &heading, const QString &text);
|
||||||
void nativeNotificationPreview();
|
void nativeNotificationPreview();
|
||||||
|
|
||||||
|
206
src/lib/plugins/ocssupport.cpp
Normal file
206
src/lib/plugins/ocssupport.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* Falkon - Qt web browser
|
||||||
|
* Copyright (C) 2019 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 "ocssupport.h"
|
||||||
|
#include "pluginproxy.h"
|
||||||
|
#include "datapaths.h"
|
||||||
|
#include "networkmanager.h"
|
||||||
|
#include "desktopnotificationsfactory.h"
|
||||||
|
#include "mainapplication.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
#include <KArchive/KZip>
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC(OcsSupport, qz_ocs_support)
|
||||||
|
|
||||||
|
OcsSupport::OcsSupport(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OcsSupport::handleUrl(const QUrl &url)
|
||||||
|
{
|
||||||
|
if (url.host() != QL1S("install")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl fileUrl;
|
||||||
|
QString fileType;
|
||||||
|
QString fileName;
|
||||||
|
|
||||||
|
const auto items = QUrlQuery(url).queryItems(QUrl::FullyDecoded);
|
||||||
|
for (const auto &item : items) {
|
||||||
|
if (item.first == QL1S("url")) {
|
||||||
|
fileUrl = QUrl(item.second);
|
||||||
|
} else if (item.first == QL1S("type")) {
|
||||||
|
fileType = item.second;
|
||||||
|
} else if (item.first == QL1S("filename")) {
|
||||||
|
fileName = item.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileType.startsWith(QL1S("falkon_"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileType != QL1S("falkon_themes") && fileType != QL1S("falkon_extensions")) {
|
||||||
|
qWarning() << "Unsupported type" << fileType;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileUrl.isValid()) {
|
||||||
|
qWarning() << "Invalid url" << fileUrl << url;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "Downloading" << fileUrl;
|
||||||
|
|
||||||
|
QNetworkReply *reply = mApp->networkManager()->get(QNetworkRequest(fileUrl));
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [=]() {
|
||||||
|
reply->deleteLater();
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qWarning() << "Error downloading" << fileUrl << reply->error() << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QBuffer buf;
|
||||||
|
buf.setData(reply->readAll());
|
||||||
|
KZip zip(&buf);
|
||||||
|
if (!zip.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning() << "Failed to open archive";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString notifyMessage;
|
||||||
|
if (fileType == QL1S("falkon_themes")) {
|
||||||
|
installTheme(zip.directory());
|
||||||
|
} else if (fileType == QL1S("falkon_extensions")) {
|
||||||
|
installExtension(zip.directory());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
OcsSupport *OcsSupport::instance()
|
||||||
|
{
|
||||||
|
return qz_ocs_support();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcsSupport::installTheme(const KArchiveDirectory *directory)
|
||||||
|
{
|
||||||
|
auto showError = []() {
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Installation failed"), tr("Failed to install theme"));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (directory->entries().size() != 1) {
|
||||||
|
qWarning() << "Invalid archive format";
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString name = directory->entries().at(0);
|
||||||
|
const KArchiveEntry *entry = directory->entry(name);
|
||||||
|
if (!entry || !entry->isDirectory()) {
|
||||||
|
qWarning() << "Invalid archive format";
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/themes");
|
||||||
|
QDir().mkpath(targetDir);
|
||||||
|
|
||||||
|
if (QFileInfo::exists(targetDir + QL1C('/') + name)) {
|
||||||
|
qWarning() << "Theme" << name << "already exists";
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Installation failed"), tr("Theme is already installed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directory->copyTo(targetDir)) {
|
||||||
|
qWarning() << "Failed to copy theme to" << targetDir;
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "Theme installed to" << targetDir;
|
||||||
|
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Theme installed"), tr("Theme was successfully installed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcsSupport::installExtension(const KArchiveDirectory *directory)
|
||||||
|
{
|
||||||
|
auto showError = []() {
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Installation failed"), tr("Failed to install extension"));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (directory->entries().size() != 1) {
|
||||||
|
qWarning() << "Invalid archive format";
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString name = directory->entries().at(0);
|
||||||
|
const KArchiveEntry *entry = directory->entry(name);
|
||||||
|
if (!entry || !entry->isDirectory()) {
|
||||||
|
qWarning() << "Invalid archive format";
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString type;
|
||||||
|
const QStringList files = static_cast<const KArchiveDirectory*>(entry)->entries();
|
||||||
|
if (files.contains(QL1S("__init__.py"))) {
|
||||||
|
type = QSL("python");
|
||||||
|
} else if (files.contains(QL1S("main.qml"))) {
|
||||||
|
type = QSL("qml");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isEmpty()) {
|
||||||
|
qWarning() << "Unsupported extension type";
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/plugins/") + type;
|
||||||
|
QDir().mkpath(targetDir);
|
||||||
|
|
||||||
|
if (QFileInfo::exists(targetDir + QL1S("/") + name)) {
|
||||||
|
qWarning() << "Extension" << name << "already exists";
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Installation failed"), tr("Extension is already installed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directory->copyTo(targetDir)) {
|
||||||
|
qWarning() << "Failed to copy extension to" << targetDir;
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qInfo() << "Extension installed to" << targetDir;
|
||||||
|
|
||||||
|
const QString fullId = QSL("%1:%2/%3").arg(type, targetDir, name);
|
||||||
|
if (!mApp->plugins()->addPlugin(fullId)) {
|
||||||
|
qWarning() << "Failed to add plugin" << fullId;
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mApp->desktopNotifications()->showNotification(tr("Extension installed"), tr("Extension was successfully installed"));
|
||||||
|
}
|
40
src/lib/plugins/ocssupport.h
Normal file
40
src/lib/plugins/ocssupport.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* Falkon - Qt web browser
|
||||||
|
* Copyright (C) 2019 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/>.
|
||||||
|
* ============================================================ */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qzcommon.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class KArchiveDirectory;
|
||||||
|
|
||||||
|
class OcsSupport : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OcsSupport(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool handleUrl(const QUrl &url);
|
||||||
|
|
||||||
|
static OcsSupport *instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void installTheme(const KArchiveDirectory *directory);
|
||||||
|
void installExtension(const KArchiveDirectory *directory);
|
||||||
|
};
|
@ -47,8 +47,7 @@ bool Plugins::Plugin::isRemovable() const
|
|||||||
|
|
||||||
bool Plugins::Plugin::operator==(const Plugin &other) const
|
bool Plugins::Plugin::operator==(const Plugin &other) const
|
||||||
{
|
{
|
||||||
return type == other.type &&
|
return type == other.type && pluginId == other.pluginId;
|
||||||
pluginId == other.pluginId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugins::Plugins(QObject* parent)
|
Plugins::Plugins(QObject* parent)
|
||||||
@ -131,6 +130,21 @@ void Plugins::removePlugin(Plugins::Plugin *plugin)
|
|||||||
emit availablePluginsChanged();
|
emit availablePluginsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Plugins::addPlugin(const QString &id)
|
||||||
|
{
|
||||||
|
Plugin plugin = loadPlugin(id);
|
||||||
|
if (plugin.type == Plugin::Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (plugin.pluginSpec.name.isEmpty()) {
|
||||||
|
qWarning() << "Invalid plugin spec of" << id << "plugin";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
registerAvailablePlugin(plugin);
|
||||||
|
emit availablePluginsChanged();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Plugins::loadSettings()
|
void Plugins::loadSettings()
|
||||||
{
|
{
|
||||||
QStringList defaultAllowedPlugins = {
|
QStringList defaultAllowedPlugins = {
|
||||||
|
@ -86,6 +86,8 @@ public:
|
|||||||
void unloadPlugin(Plugin* plugin);
|
void unloadPlugin(Plugin* plugin);
|
||||||
void removePlugin(Plugin *plugin);
|
void removePlugin(Plugin *plugin);
|
||||||
|
|
||||||
|
bool addPlugin(const QString &id);
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
// SpeedDial
|
// SpeedDial
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "ui_jsprompt.h"
|
#include "ui_jsprompt.h"
|
||||||
#include "passwordmanager.h"
|
#include "passwordmanager.h"
|
||||||
#include "scripts.h"
|
#include "scripts.h"
|
||||||
|
#include "ocssupport.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -453,6 +454,10 @@ bool WebPage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::Navigatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (url.scheme() == QL1S("ocs") && OcsSupport::instance()->handleUrl(url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const bool result = QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
|
const bool result = QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
Loading…
Reference in New Issue
Block a user