mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 02:36:34 +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
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
# Mandatory: KF5
|
||||
find_package(KF5 REQUIRED COMPONENTS Archive)
|
||||
|
||||
# KF5I18n: Mandatory with downloaded translations (only for ki18n_install)
|
||||
if (EXISTS "${CMAKE_SOURCE_DIR}/po")
|
||||
find_package(KF5I18n REQUIRED)
|
||||
|
@ -156,6 +156,7 @@ set(SRCS ${SRCS}
|
||||
plugins/pluginproxy.cpp
|
||||
plugins/plugins.cpp
|
||||
plugins/speeddial.cpp
|
||||
plugins/ocssupport.cpp
|
||||
plugins/qml/qmlpluginloader.cpp
|
||||
plugins/qml/qmlplugin.cpp
|
||||
plugins/qml/qmlplugins.cpp
|
||||
@ -348,6 +349,7 @@ target_link_libraries(FalkonPrivate
|
||||
Qt5::PrintSupport
|
||||
Qt5::QuickWidgets
|
||||
Qt5::WebChannel
|
||||
KF5::Archive
|
||||
${OPENSSL_CRYPTO_LIBRARY}
|
||||
)
|
||||
|
||||
|
@ -61,6 +61,11 @@ bool DesktopNotificationsFactory::supportsNativeNotifications() const
|
||||
#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)
|
||||
{
|
||||
if (!m_enabled) {
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
bool supportsNativeNotifications() const;
|
||||
|
||||
void showNotification(const QString &heading, const QString &text);
|
||||
void showNotification(const QPixmap &icon, const QString &heading, const QString &text);
|
||||
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
|
||||
{
|
||||
return type == other.type &&
|
||||
pluginId == other.pluginId;
|
||||
return type == other.type && pluginId == other.pluginId;
|
||||
}
|
||||
|
||||
Plugins::Plugins(QObject* parent)
|
||||
@ -131,6 +130,21 @@ void Plugins::removePlugin(Plugins::Plugin *plugin)
|
||||
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()
|
||||
{
|
||||
QStringList defaultAllowedPlugins = {
|
||||
|
@ -86,6 +86,8 @@ public:
|
||||
void unloadPlugin(Plugin* plugin);
|
||||
void removePlugin(Plugin *plugin);
|
||||
|
||||
bool addPlugin(const QString &id);
|
||||
|
||||
void shutdown();
|
||||
|
||||
// SpeedDial
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "ui_jsprompt.h"
|
||||
#include "passwordmanager.h"
|
||||
#include "scripts.h"
|
||||
#include "ocssupport.h"
|
||||
|
||||
#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);
|
||||
|
||||
if (result) {
|
||||
|
Loading…
Reference in New Issue
Block a user