diff --git a/webenginepart/src/CMakeLists.txt b/webenginepart/src/CMakeLists.txt
--- a/webenginepart/src/CMakeLists.txt
+++ b/webenginepart/src/CMakeLists.txt
@@ -13,6 +13,7 @@
webhistoryinterface.cpp
webenginepartdownloadmanager.cpp
webenginewallet.cpp
+ webengineparterrorschemehandler.cpp
settings/webenginesettings.cpp
settings/webengine_filter.cpp
ui/searchbar.cpp
@@ -33,6 +34,7 @@
KF5::SonnetCore
KF5::WindowSystem # for KUserTimestamp
KF5::Wallet
+ KF5::IconThemes #for KIconLoader used by WebEnginePartErrorSchemeHandler
)
target_include_directories(kwebenginepartlib PUBLIC
@@ -50,3 +52,5 @@
install(FILES webenginepart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(FILES webenginepart.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/webenginepart)
+
+install(FILES error.html DESTINATION ${KDE_INSTALL_DATADIR}/webenginepart)
diff --git a/webenginepart/src/error.html b/webenginepart/src/error.html
new file mode 100644
--- /dev/null
+++ b/webenginepart/src/error.html
@@ -0,0 +1,61 @@
+
+
+%1
+
+
+
+
+
+
+%4
+
+
+
+
diff --git a/webenginepart/src/webenginepart.h b/webenginepart/src/webenginepart.h
--- a/webenginepart/src/webenginepart.h
+++ b/webenginepart/src/webenginepart.h
@@ -43,6 +43,7 @@
class KUrlLabel;
class WebEngineBrowserExtension;
class WebEngineWallet;
+class WebEngineErrorSchemeHandler;
/**
* A KPart wrapper for the QtWebEngine's browser rendering engine.
diff --git a/webenginepart/src/webenginepart.cpp b/webenginepart/src/webenginepart.cpp
--- a/webenginepart/src/webenginepart.cpp
+++ b/webenginepart/src/webenginepart.cpp
@@ -35,6 +35,7 @@
#include "websslinfo.h"
#include "webhistoryinterface.h"
#include "webenginewallet.h"
+#include "webengineparterrorschemehandler.h"
#include "ui/searchbar.h"
#include "ui/passwordbar.h"
@@ -71,6 +72,7 @@
#include
#include
#include "utils.h"
+#include
WebEnginePart::WebEnginePart(QWidget *parentWidget, QObject *parent,
const QByteArray& cachedHistory, const QStringList& /*args*/)
@@ -84,6 +86,10 @@
m_featurePermissionBar(0),
m_wallet(Q_NULLPTR)
{
+ QWebEngineProfile *prof = QWebEngineProfile::defaultProfile();
+ if (!prof->urlSchemeHandler("error")) {
+ prof->installUrlSchemeHandler("error", new WebEnginePartErrorSchemeHandler(prof));
+ }
KAboutData about = KAboutData(QStringLiteral("webenginepart"),
i18nc("Program Name", "WebEnginePart"),
/*version*/ QStringLiteral("1.3.0"),
diff --git a/webenginepart/src/webengineparterrorschemehandler.h b/webenginepart/src/webengineparterrorschemehandler.h
new file mode 100644
--- /dev/null
+++ b/webenginepart/src/webengineparterrorschemehandler.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 2018 Stefano Crocco
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+ *
+*/
+
+#ifndef WEBENGINEPARTERRORSCHEMEHANDLER_H
+#define WEBENGINEPARTERRORSCHEMEHANDLER_H
+
+#include
+#include
+#include
+
+class QBuffer;
+
+class WebEnginePartErrorSchemeHandler : public QWebEngineUrlSchemeHandler{
+
+ Q_OBJECT
+
+public:
+
+ WebEnginePartErrorSchemeHandler(QObject *parent = Q_NULLPTR);
+
+ ~WebEnginePartErrorSchemeHandler(){}
+
+ void requestStarted(QWebEngineUrlRequestJob * job) Q_DECL_OVERRIDE;
+
+private:
+
+ struct ErrorInfo{
+ int code;
+ QString text;
+ QUrl requestUrl;
+ };
+
+ ErrorInfo parseErrorUrl(const QUrl& url);
+
+ void writeErrorPage(QBuffer *buf, const ErrorInfo &info);
+
+ QString readWarningIconData() const;
+
+ const QString m_warningIconData;
+};
+
+#endif //WEBENGINEPARTERRORSCHEMEHANDLER_H
diff --git a/webenginepart/src/webengineparterrorschemehandler.cpp b/webenginepart/src/webengineparterrorschemehandler.cpp
new file mode 100644
--- /dev/null
+++ b/webenginepart/src/webengineparterrorschemehandler.cpp
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 2018 Stefano Crocco
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+ *
+*/
+
+#include "webengineparterrorschemehandler.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "utils.h"
+
+WebEnginePartErrorSchemeHandler::WebEnginePartErrorSchemeHandler(QObject* parent):
+ QWebEngineUrlSchemeHandler(parent), m_warningIconData(readWarningIconData())
+{
+}
+
+QString WebEnginePartErrorSchemeHandler::readWarningIconData() const
+{
+ QString data;
+ QString path = KIconLoader::global()->iconPath("dialog-warning", -KIconLoader::SizeHuge);
+ if (path.isEmpty()) {
+ return data;
+ }
+ QFile f(path);
+ if (f.open(QIODevice::ReadOnly)) {
+ QMimeDatabase db;
+ QMimeType mime = db.mimeTypeForFile(f.fileName());
+ data += QL1S("data:");
+ data += mime.isValid() ? mime.name() : "application/octet-stream";
+ data += QL1S(";base64,");
+ data += f.readAll().toBase64();
+ }
+ return data;
+
+}
+
+void WebEnginePartErrorSchemeHandler::requestStarted(QWebEngineUrlRequestJob* job)
+{
+ QBuffer *buf = new QBuffer;
+ buf->open(QBuffer::ReadWrite);
+ connect(buf, &QIODevice::aboutToClose, buf, &QObject::deleteLater);
+ ErrorInfo ei = parseErrorUrl(job->requestUrl());
+ writeErrorPage(buf, ei);
+ buf->seek(0);
+ job->reply("text/html", buf);
+}
+
+WebEnginePartErrorSchemeHandler::ErrorInfo WebEnginePartErrorSchemeHandler::parseErrorUrl(const QUrl& url)
+{
+ ErrorInfo ei;
+ ei.requestUrl = QUrl(url.fragment());
+ if (ei.requestUrl.isValid()) {
+ QString query = url.query(QUrl::FullyDecoded);
+ QRegularExpression pattern("error=(\\d+)&errText=(.*)");
+ QRegularExpressionMatch match = pattern.match(query);
+ int error = match.captured(1).toInt();
+ // error=0 isn't a valid error code, so 0 means it's missing from the URL
+ if (error == 0) {
+ error = KIO::ERR_UNKNOWN;
+ }
+ ei.text = match.captured(2);
+ ei.code = error;
+ }
+ return ei;
+}
+
+void WebEnginePartErrorSchemeHandler::writeErrorPage(QBuffer* buf, const WebEnginePartErrorSchemeHandler::ErrorInfo& info)
+{
+ QString errorName, techName, description;
+ QStringList causes, solutions;
+
+ QByteArray raw = KIO::rawErrorDetail(info.code, info.text, &info.requestUrl);
+ QDataStream stream(raw);
+
+ stream >> errorName >> techName >> description >> causes >> solutions;
+
+ QFile file(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QL1S("webenginepart/error.html")));
+ if (!file.open(QIODevice::ReadOnly)) {
+ buf->write(i18n("Unable to display error message
"
+ "The error template file error.html could not be "
+ "found.
").toUtf8());
+ return;
+ }
+
+ QString html(QL1S(file.readAll()));
+
+ QString doc(QL1S(""));
+ doc += i18n("The requested operation could not be completed");
+ doc += QL1S("
");
+ doc += errorName;
+ doc += QL1S("
");
+
+ if (!techName.isEmpty()) {
+ doc += QL1S("");
+ doc += i18n("Technical Reason: %1", techName);
+ doc += QL1S("
");
+ }
+
+ doc += QL1S("");
+ doc += i18n("Details of the Request:");
+ doc += QL1S("
- ");
+ // escape URL twice: once for i18n, and once for HTML.
+ doc += i18n("URL: %1", Qt::escape(Qt::escape(info.requestUrl.toDisplayString())));
+ doc += QL1S("
- ");
+
+ const QString protocol(info.requestUrl.scheme());
+ if (!protocol.isEmpty()) {
+ // escape protocol twice: once for i18n, and once for HTML.
+ doc += i18n("Protocol: %1", Qt::escape(Qt::escape(protocol)));
+ doc += QL1S("
- ");
+ }
+
+ doc += i18n("Date and Time: %1",
+ QLocale().toString(QDateTime::currentDateTime(), QLocale::LongFormat));
+ doc += QL1S("
- ");
+ // escape info.text twice: once for i18n, and once for HTML.
+ doc += i18n("Additional Information: %1", Qt::escape(Qt::escape(info.text)));
+ doc += QL1S("
");
+ doc += i18n("Description:");
+ doc += QL1S("
");
+ doc += description;
+ doc += QL1S("
");
+
+ if (!causes.isEmpty()) {
+ doc += QL1S("");
+ doc += i18n("Possible Causes:");
+ doc += QL1S("
- ");
+ doc += causes.join("
- ");
+ doc += QL1S("
");
+ }
+
+ if (!solutions.isEmpty()) {
+ doc += QL1S("");
+ doc += i18n("Possible Solutions:");
+ doc += QL1S("
- ");
+ doc += solutions.join("
- ");
+ doc += QL1S("
");
+ }
+
+ QString title(i18n("Error: %1", errorName));
+ QString direction(QApplication::isRightToLeft() ? "rtl" : "ltr");
+ buf->write(html.arg(title, direction, m_warningIconData, doc).toUtf8());
+}
+