diff --git a/add-kwallet-support-to-webengine.patch b/add-kwallet-support-to-webengine.patch deleted file mode 100644 index 8bd4d84..0000000 --- a/add-kwallet-support-to-webengine.patch +++ /dev/null @@ -1,1256 +0,0 @@ -From 56ea2a32d2f1d9f4e6c97b27080cf8144a932ee3 Mon Sep 17 00:00:00 2001 -From: Stefano Crocco -Date: Sun, 14 Jan 2018 11:25:17 +0100 -Subject: Add back KWallet support to Konqueror - -Summary: -Added back the ability to store user names and passwords to KWallet and automatically fill them when loading a page. - -I copied the files `kwebwallet.cpp` and `kwebwallet.h` from the `KDEWebKit` framework and modified it to adapt to `QWebEngine`. In particular, I needed to modify the way form data is passed from javascript to C++ serializing it using JSON and read it back using `QJsonDocument`. Also, since `QWebEnginePage` doesn't allow to access frames from the C++ side, I needed to remove all the code dealing with recurisve searches and implement it in javascript. - -As the old code, this intentionally doesn't work with input elements with the `autocomplete` attribute set to `false`. - -I've not modified the copyright information in the files I copied from `KDEWebKit` as I don't know which is the correct way to do so: I must make clear my files are based on the work on other people but at the same time that I've changed them: how do I do this? - -Test Plan: I tried to access several sites requiring a login in, asking Konqueror to save the password, then logging out and visiting the page again. Except when the `autocomplete` attribute was `false` (checked by looking at the html code), Konqueror always saved and restored login information correctly. - -Reviewers: dfaure - -Reviewed By: dfaure - -Differential Revision: https://phabricator.kde.org/D10178 ---- - webenginepart/src/CMakeLists.txt | 4 + - webenginepart/src/webenginepage.cpp | 14 +- - webenginepart/src/webenginepage.h | 7 +- - webenginepart/src/webenginepart.cpp | 62 +-- - webenginepart/src/webenginepart.h | 5 + - webenginepart/src/webenginepartfactory.cpp | 1 + - webenginepart/src/webenginewallet.cpp | 599 +++++++++++++++++++++++++++++ - webenginepart/src/webenginewallet.h | 305 +++++++++++++++ - 8 files changed, 964 insertions(+), 33 deletions(-) - create mode 100644 webenginepart/src/webenginewallet.cpp - create mode 100644 webenginepart/src/webenginewallet.h - -diff --git a/webenginepart/src/CMakeLists.txt b/webenginepart/src/CMakeLists.txt -index bfac067..fffce88 100644 ---- a/webenginepart/src/CMakeLists.txt -+++ b/webenginepart/src/CMakeLists.txt -@@ -1,3 +1,5 @@ -+find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Wallet) -+ - include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}) - - set(kwebenginepartlib_LIB_SRCS -@@ -8,6 +10,7 @@ set(kwebenginepartlib_LIB_SRCS - websslinfo.cpp - webhistoryinterface.cpp - webenginepartdownloadmanager.cpp -+ webenginewallet.cpp - settings/webenginesettings.cpp - settings/webengine_filter.cpp - ui/searchbar.cpp -@@ -27,6 +30,7 @@ target_link_libraries(kwebenginepartlib Qt5::Core Qt5::DBus Qt5::Gui Qt5::Widget - KF5::Parts - KF5::SonnetCore - KF5::WindowSystem # for KUserTimestamp -+ KF5::Wallet - ) - - target_include_directories(kwebenginepartlib PUBLIC -diff --git a/webenginepart/src/webenginepage.cpp b/webenginepart/src/webenginepage.cpp -index 212e189..615e8f7 100644 ---- a/webenginepart/src/webenginepage.cpp -+++ b/webenginepart/src/webenginepage.cpp -@@ -27,6 +27,7 @@ - #include "webengineview.h" - #include "settings/webenginesettings.h" - #include "webenginepartdownloadmanager.h" -+#include "webenginewallet.h" - #include - #include - -@@ -72,7 +73,8 @@ WebEnginePage::WebEnginePage(WebEnginePart *part, QWidget *parent) - m_kioErrorCode(0), - m_ignoreError(false), - m_part(part), -- m_passwdServerClient(new KPasswdServerClient) -+ m_passwdServerClient(new KPasswdServerClient), -+ m_wallet(Q_NULLPTR) - { - if (view()) - WebEngineSettings::self()->computeFontSizes(view()->logicalDpiY()); -@@ -94,6 +96,7 @@ WebEnginePage::WebEnginePage(WebEnginePart *part, QWidget *parent) - this->profile()->setHttpUserAgent(this->profile()->httpUserAgent() + " Konqueror (WebEnginePart)"); - } - WebEnginePartDownloadManager::instance()->addPage(this); -+ m_wallet = new WebEngineWallet(this, parent ? parent->window()->winId() : 0); - } - - WebEnginePage::~WebEnginePage() -@@ -204,8 +207,9 @@ bool WebEnginePage::acceptNavigationRequest(const QUrl& url, NavigationType type - bool inPageRequest = true; - switch (type) { - case QWebEnginePage::NavigationTypeFormSubmitted: -- //if (!checkFormData(request)) -- // return false; -+ if (!checkFormData(url)) -+ return false; -+ m_wallet->saveFormData(this); - break; - #if 0 - case QWebEnginePage::NavigationTypeFormResubmitted: -@@ -548,9 +552,9 @@ bool WebEnginePage::checkLinkSecurity(const QNetworkRequest &req, NavigationType - return true; - } - --bool WebEnginePage::checkFormData(const QNetworkRequest &req) const -+bool WebEnginePage::checkFormData(const QUrl &url) const - { -- const QString scheme (req.url().scheme()); -+ const QString scheme (url.scheme()); - - if (m_sslInfo.isValid() && - !scheme.compare(QL1S("https")) && !scheme.compare(QL1S("mailto")) && -diff --git a/webenginepart/src/webenginepage.h b/webenginepart/src/webenginepage.h -index 8fa0386..cb3d5ed 100644 ---- a/webenginepart/src/webenginepage.h -+++ b/webenginepart/src/webenginepage.h -@@ -40,6 +40,7 @@ class WebSslInfo; - class WebEnginePart; - class QWebEngineDownloadItem; - class KPasswdServerClient; -+class WebEngineWallet; - - class WebEnginePage : public QWebEnginePage - { -@@ -64,6 +65,8 @@ public: - - void download(const QUrl &url, bool newWindow = false); - -+ WebEngineWallet* wallet() const {return m_wallet;} -+ - Q_SIGNALS: - /** - * This signal is emitted whenever a user cancels/aborts a load resource -@@ -107,7 +110,7 @@ protected Q_SLOTS: - - private: - bool checkLinkSecurity(const QNetworkRequest& req, NavigationType type) const; -- bool checkFormData(const QNetworkRequest& req) const; -+ bool checkFormData(const QUrl& url) const; - bool handleMailToUrl (const QUrl& , NavigationType type) const; - void setPageJScriptPolicy(const QUrl& url); - -@@ -121,6 +124,7 @@ private: - QPointer m_part; - - QScopedPointer m_passwdServerClient; -+ WebEngineWallet *m_wallet; - }; - - -@@ -158,6 +162,7 @@ private: - KParts::WindowArgs m_windowArgs; - WebWindowType m_type; - bool m_createNewWindow; -+ WebEngineWallet* m_wallet; - }; - - #endif // WEBENGINEPAGE_H -diff --git a/webenginepart/src/webenginepart.cpp b/webenginepart/src/webenginepart.cpp -index 10bbffc..66edce7 100644 ---- a/webenginepart/src/webenginepart.cpp -+++ b/webenginepart/src/webenginepart.cpp -@@ -34,6 +34,7 @@ - #include "webenginepage.h" - #include "websslinfo.h" - #include "webhistoryinterface.h" -+#include "webenginewallet.h" - - #include "ui/searchbar.h" - #include "ui/passwordbar.h" -@@ -80,7 +81,8 @@ WebEnginePart::WebEnginePart(QWidget *parentWidget, QObject *parent, - m_statusBarWalletLabel(0), - m_searchBar(0), - m_passwordBar(0), -- m_featurePermissionBar(0) -+ m_featurePermissionBar(0), -+ m_wallet(Q_NULLPTR) - { - KAboutData about = KAboutData(QStringLiteral("webenginepart"), - i18nc("Program Name", "WebEnginePart"), -@@ -168,6 +170,7 @@ WebEnginePart::WebEnginePart(QWidget *parentWidget, QObject *parent, - - // Load plugins once we are fully ready - loadPlugins(); -+ setWallet(page()->wallet()); - } - - WebEnginePart::~WebEnginePart() -@@ -311,17 +314,25 @@ void WebEnginePart::connectWebEnginePageSignals(WebEnginePage* page) - m_browserExtension->setIconUrl(url); - } - }); -+} - --#if 0 -- KWebWallet *wallet = page->wallet(); -- if (wallet) { -- connect(wallet, SIGNAL(saveFormDataRequested(QString,QUrl)), -- this, SLOT(slotSaveFormDataRequested(QString,QUrl))); -- connect(wallet, SIGNAL(fillFormRequestCompleted(bool)), -- this, SLOT(slotFillFormRequestCompleted(bool))); -- connect(wallet, SIGNAL(walletClosed()), this, SLOT(slotWalletClosed())); -+void WebEnginePart::setWallet(WebEngineWallet* wallet) -+{ -+ if(m_wallet){ -+ disconnect(m_wallet, &WebEngineWallet::saveFormDataRequested, -+ this, &WebEnginePart::slotSaveFormDataRequested); -+ disconnect(m_wallet, &WebEngineWallet::fillFormRequestCompleted, -+ this, &WebEnginePart::slotFillFormRequestCompleted); -+ disconnect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::slotWalletClosed); -+ } -+ m_wallet = wallet; -+ if (m_wallet) { -+ connect(m_wallet, &WebEngineWallet::saveFormDataRequested, -+ this, &WebEnginePart::slotSaveFormDataRequested); -+ connect(m_wallet, &WebEngineWallet::fillFormRequestCompleted, -+ this, &WebEnginePart::slotFillFormRequestCompleted); -+ connect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::slotWalletClosed); - } --#endif - } - - bool WebEnginePart::openUrl(const QUrl &_u) -@@ -451,15 +462,15 @@ void WebEnginePart::slotLoadFinished (bool ok) - } - if (!Utils::isBlankUrl(url())) { - m_hasCachedFormData = false; -- - if (WebEngineSettings::self()->isNonPasswordStorableSite(url().host())) { - addWalletStatusBarIcon(); -- } else { -+ } -+ else { - // Attempt to fill the web form... --// KWebWallet *webWallet = page() ? page()->wallet() : 0; --// if (webWallet) { --// webWallet->fillFormData(frame, false); --// } -+ WebEngineWallet *wallet = page() ? page()->wallet() : 0; -+ if (wallet){ -+ wallet->fillFormData(page()); -+ } - } - } - -@@ -766,10 +777,10 @@ void WebEnginePart::slotDeleteNonPasswordStorableSite() - - void WebEnginePart::slotRemoveCachedPasswords() - { -- if (!page()) // || !page()->wallet()) -+ if (!page() || !page()->wallet()) - return; - --// page()->wallet()->removeFormData(page()->mainFrame(), true); -+ page()->wallet()->removeFormData(page()); - m_hasCachedFormData = false; - } - -@@ -822,8 +833,8 @@ void WebEnginePart::slotShowFeaturePermissionBar(QWebEnginePage::Feature feature - this, SLOT(slotFeaturePermissionGranted(QWebEnginePage::Feature))); - connect(m_featurePermissionBar, SIGNAL(permissionDenied(QWebEnginePage::Feature)), - this, SLOT(slotFeaturePermissionDenied(QWebEnginePage::Feature))); --// connect(m_passwordBar, SIGNAL(done()), --// this, SLOT(slotSaveFormDataDone())); -+ connect(m_passwordBar, SIGNAL(done()), -+ this, SLOT(slotSaveFormDataDone())); - QBoxLayout* lay = qobject_cast(widget()->layout()); - if (lay) - lay->insertWidget(0, m_featurePermissionBar); -@@ -862,19 +873,16 @@ void WebEnginePart::slotSaveFormDataRequested (const QString& key, const QUrl& u - - if (!m_passwordBar) { - m_passwordBar = new PasswordBar(widget()); --#if 0 -- KWebWallet* wallet = page()->wallet(); -- if (!wallet) { -- kWarning() << "No wallet instance found! This should never happen!"; -+ if (!m_wallet) { -+ qDebug() << "No m_wallet instance found! This should never happen!"; - return; - } - connect(m_passwordBar, SIGNAL(saveFormDataAccepted(QString)), -- wallet, SLOT(acceptSaveFormDataRequest(QString))); -+ m_wallet, SLOT(acceptSaveFormDataRequest(QString))); - connect(m_passwordBar, SIGNAL(saveFormDataRejected(QString)), -- wallet, SLOT(rejectSaveFormDataRequest(QString))); -+ m_wallet, SLOT(rejectSaveFormDataRequest(QString))); - connect(m_passwordBar, SIGNAL(done()), - this, SLOT(slotSaveFormDataDone())); --#endif - } - - Q_ASSERT(m_passwordBar); -diff --git a/webenginepart/src/webenginepart.h b/webenginepart/src/webenginepart.h -index 6889e6d..91afa42 100644 ---- a/webenginepart/src/webenginepart.h -+++ b/webenginepart/src/webenginepart.h -@@ -42,6 +42,7 @@ class PasswordBar; - class FeaturePermissionBar; - class KUrlLabel; - class WebEngineBrowserExtension; -+class WebEngineWallet; - - /** - * A KPart wrapper for the QtWebEngine's browser rendering engine. -@@ -98,6 +99,9 @@ public: - void connectWebEnginePageSignals(WebEnginePage* page); - - void slotShowFeaturePermissionBar(QWebEnginePage::Feature); -+ -+ void setWallet(WebEngineWallet* wallet); -+ - protected: - /** - * Re-implemented for internal reasons. API remains unaffected. -@@ -160,6 +164,7 @@ private: - WebEngineBrowserExtension* m_browserExtension; - KParts::StatusBarExtension* m_statusBarExtension; - WebEngineView* m_webView; -+ WebEngineWallet* m_wallet; - }; - - #endif // WEBENGINEPART_H -diff --git a/webenginepart/src/webenginepartfactory.cpp b/webenginepart/src/webenginepartfactory.cpp -index 04853bd..7a877b4 100644 ---- a/webenginepart/src/webenginepartfactory.cpp -+++ b/webenginepart/src/webenginepartfactory.cpp -@@ -24,6 +24,7 @@ - - #include - -+ - WebEngineFactory::~WebEngineFactory() - { - // kDebug() << this; -diff --git a/webenginepart/src/webenginewallet.cpp b/webenginepart/src/webenginewallet.cpp -new file mode 100644 -index 0000000..f501b27 ---- /dev/null -+++ b/webenginepart/src/webenginewallet.cpp -@@ -0,0 +1,599 @@ -+/* -+ * This file is part of the KDE project. -+ * -+ * Copyright (C) 2009 Dawit Alemayehu -+ * Copyright (C) 2018 Stefano Crocco -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public License -+ * along with this library; see the file COPYING.LIB. If not, write to -+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ * -+ */ -+ -+#include "webenginewallet.h" -+#include "webenginepage.h" -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define QL1S(x) QLatin1String(x) -+#define QL1C(x) QLatin1Char(x) -+ -+// Javascript used to extract/set data from
elements. -+static const char s_fillableFormElementExtractorJs[] = "(function(){ " -+" function findFormsRecursive(wnd, existingList, path){" -+" findFormsInFrame(wnd, existingList, path);" -+" frameList = wnd.frames;" -+" for(var i = 0; i < frameList.length; ++i) {" -+" var newPath = path.concat(i);" -+" findFormsRecursive(frameList[i], existingList, newPath);" -+" }" -+" }" -+" function findFormsInFrame(frm, existingList, path){" -+" var url = frm.location;" -+" var formList;" -+" try{ formList = frm.document.forms; } " -+" catch(e){" -+" return;" -+" }" -+" if (formList.length > 0) { " -+" for (var i = 0; i < formList.length; ++i) { " -+" var inputList = formList[i].elements; " -+" if (inputList.length < 1) { " -+" continue; " -+" } " -+" var formObject = new Object; " -+" formObject.url = url;" -+" formObject.name = formList[i].name; " -+" if (typeof(formObject.name) != 'string') { " -+" formObject.name = String(formList[i].id); " -+" } " -+" formObject.index = i; " -+" formObject.elements = new Array; " -+" for (var j = 0; j < inputList.length; ++j) { " -+" if (inputList[j].type != 'text' && inputList[j].type != 'email' && inputList[j].type != 'password') { " -+" continue; " -+" } " -+" if (inputList[j].disabled || inputList[j].autocomplete == 'off') { " -+" continue; " -+" } " -+" var element = new Object; " -+" element.name = inputList[j].name; " -+" if (typeof(element.name) != 'string' ) { " -+" element.name = String(inputList[j].id); " -+" } " -+" element.value = String(inputList[j].value); " -+" element.type = String(inputList[j].type); " -+" element.readonly = Boolean(inputList[j].readOnly); " -+" formObject.elements.push(element); " -+" } " -+" if (formObject.elements.length > 0) { " -+" formObject.framePath = path;" -+" console.log(JSON.stringify(formObject));" -+" existingList.push(JSON.stringify(formObject)); " -+" } " -+" } " -+" } " -+" }" -+" var forms = new Array;" -+" findFormsRecursive(window, forms, []);" -+" return forms;" -+"})()"; -+ -+//javascript used to fill a single form element -+static const char s_javascriptFillInputFragment[] = "var frm = window;" -+" for(var i=0; i < [%1].length; ++i) frm=frm.frames[i];" -+" if (frm.document.forms['%2'] && frm.document.forms['%2'].elements['%3']){" -+" frm.document.forms['%2'].elements['%3'].value='%4';\n" -+" }"; -+ -+ -+/** -+ * Creates key used to store and retrieve form data. -+ * -+ */ -+static QString walletKey(WebEngineWallet::WebForm form) -+{ -+ QString key = form.url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment); -+ key += QL1C('#'); -+ key += form.name; -+ return key; -+} -+ -+static QUrl urlForFrame(const QUrl &frameUrl, const QUrl &pageUrl) -+{ -+ return (frameUrl.isEmpty() || frameUrl.isRelative() ? pageUrl.resolved(frameUrl) : frameUrl); -+} -+ -+class WebEngineWallet::WebEngineWalletPrivate -+{ -+public: -+ struct FormsData { -+ QPointer page; -+ WebEngineWallet::WebFormList forms; -+ }; -+ -+ typedef std::function WebWalletCallback; -+ -+ WebEngineWalletPrivate(WebEngineWallet *parent); -+ -+ void withFormData(WebEnginePage *page, WebWalletCallback callback, bool fillform = true, bool ignorepasswd = false); -+ WebFormList parseFormData(const QVariant &result, const QUrl &url, bool fillform = true, bool ignorepasswd = false); -+ void performFormDataParsing(const QVariant &result, const QUrl &url, WebWalletCallback callback, bool fillform, bool ignorepasswd); -+ void fillDataFromCache(WebEngineWallet::WebFormList &formList); -+ void saveDataToCache(const QString &key); -+ void removeDataFromCache(const WebFormList &formList); -+ void openWallet(); -+ -+ // Private slots... -+ void _k_openWalletDone(bool); -+ void _k_walletClosed(); -+ -+ WId wid; -+ WebEngineWallet *q; -+ QScopedPointer wallet; -+ WebEngineWallet::WebFormList pendingRemoveRequests; -+ QHash pendingFillRequests; -+ QHash pendingSaveRequests; -+ QSet confirmSaveRequestOverwrites; -+}; -+ -+WebEngineWallet::WebEngineWalletPrivate::WebEngineWalletPrivate(WebEngineWallet *parent) -+ : wid(0), q(parent) -+{ -+} -+ -+WebEngineWallet::WebFormList WebEngineWallet::WebEngineWalletPrivate::parseFormData(const QVariant &result, const QUrl &url, bool fillform, bool ignorepasswd) -+{ -+ const QVariantList results(result.toList()); -+ WebEngineWallet::WebFormList list; -+ Q_FOREACH (const QVariant &formVariant, results) { -+ QJsonDocument doc = QJsonDocument::fromJson(formVariant.toString().toUtf8()); -+ const QVariantMap map = doc.toVariant().toMap(); -+ WebEngineWallet::WebForm form; -+ form.url = urlForFrame(QUrl(map[QL1S("url")].toString()), url); -+ form.name = map[QL1S("name")].toString(); -+ form.index = map[QL1S("index")].toString(); -+ form.framePath = map["framePath"].toStringList().join(","); -+ bool formHasPasswords = false; -+ const QVariantList elements = map[QL1S("elements")].toList(); -+ QVector inputFields; -+ Q_FOREACH (const QVariant &element, elements) { -+ QVariantMap elementMap(element.toMap()); -+ const QString name(elementMap[QL1S("name")].toString()); -+ const QString value(ignorepasswd ? QString() : elementMap[QL1S("value")].toString()); -+ if (name.isEmpty()) { -+ continue; -+ } -+ if (fillform && elementMap[QL1S("readonly")].toBool()) { -+ continue; -+ } -+ if (elementMap[QL1S("type")].toString().compare(QL1S("password"), Qt::CaseInsensitive) == 0) { -+ if (!fillform && value.isEmpty()) { -+ continue; -+ } -+ formHasPasswords = true; -+ } -+ inputFields.append(qMakePair(name, value)); -+ } -+ // Only add the input fields on form save requests... -+ if (formHasPasswords || fillform) { -+ form.fields = inputFields; -+ } -+ -+ // Add the form to the list if we are saving it or it has cached data. -+ if ((fillform && q->hasCachedFormData(form)) || (!fillform && !form.fields.isEmpty())) { -+ list << form; -+ } -+ } -+ return list; -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::withFormData(WebEnginePage* page, WebWalletCallback callback, bool fillform, bool ignorepasswd) -+{ -+ Q_ASSERT(page); -+ QUrl url = page->url(); -+ auto internalCallback = [this, url, fillform, ignorepasswd, callback](const QVariant &result){ -+ WebFormList res = parseFormData(result, url, fillform, ignorepasswd); -+ callback(res); -+ }; -+ page->runJavaScript(QL1S(s_fillableFormElementExtractorJs), internalCallback); -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::fillDataFromCache(WebEngineWallet::WebFormList &formList) -+{ -+ if (!wallet) { -+ qWarning() << "Unable to retrieve form data from wallet"; -+ return; -+ } -+ -+ QString lastKey; -+ QMap cachedValues; -+ QMutableVectorIterator formIt(formList); -+ -+ while (formIt.hasNext()) { -+ WebEngineWallet::WebForm &form = formIt.next(); -+ const QString key(walletKey(form)); -+ if (key != lastKey && wallet->readMap(key, cachedValues) != 0) { -+ qWarning() << "Unable to read form data for key:" << key; -+ continue; -+ } -+ -+ for (int i = 0, count = form.fields.count(); i < count; ++i) { -+ form.fields[i].second = cachedValues.value(form.fields[i].first); -+ } -+ lastKey = key; -+ } -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::saveDataToCache(const QString &key) -+{ -+ // Make sure the specified keys exists before acting on it. See BR# 270209. -+ if (!pendingSaveRequests.contains(key)) { -+ return; -+ } -+ -+ bool success = false; -+ const QUrl url = pendingSaveRequests.value(key).first().url; -+ -+ if (wallet) { -+ int count = 0; -+ const WebEngineWallet::WebFormList list = pendingSaveRequests.value(key); -+ QVectorIterator formIt(list); -+ -+ while (formIt.hasNext()) { -+ QMap values, storedValues; -+ const WebEngineWallet::WebForm form = formIt.next(); -+ const QString accessKey = walletKey(form); -+ if (confirmSaveRequestOverwrites.contains(url)) { -+ confirmSaveRequestOverwrites.remove(url); -+ const int status = wallet->readMap(accessKey, storedValues); -+ if (status == 0 && storedValues.count()) { -+ QVectorIterator fieldIt(form.fields); -+ while (fieldIt.hasNext()) { -+ const WebEngineWallet::WebForm::WebField field = fieldIt.next(); -+ if (storedValues.contains(field.first) && -+ storedValues.value(field.first) != field.second) { -+ emit q->saveFormDataRequested(key, url); -+ return; -+ } -+ } -+ // If we got here it means the new credential is exactly -+ // the same as the one already cached ; so skip the -+ // re-saving part... -+ success = true; -+ continue; -+ } -+ } -+ QVectorIterator fieldIt(form.fields); -+ while (fieldIt.hasNext()) { -+ const WebEngineWallet::WebForm::WebField field = fieldIt.next(); -+ values.insert(field.first, field.second); -+ } -+ -+ if (wallet->writeMap(accessKey, values) == 0) { -+ count++; -+ } else { -+ qWarning() << "Unable to write form data to wallet"; -+ } -+ } -+ -+ if (list.isEmpty() || count > 0) { -+ success = true; -+ } -+ -+ pendingSaveRequests.remove(key); -+ } else { -+ qWarning() << "NULL Wallet instance!"; -+ } -+ -+ emit q->saveFormDataCompleted(url, success); -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::openWallet() -+{ -+ if (!wallet.isNull()) { -+ return; -+ } -+ -+ wallet.reset(KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), -+ wid, KWallet::Wallet::Asynchronous)); -+ -+ if (wallet.isNull()) { -+ return; -+ } -+ -+ connect(wallet.data(), SIGNAL(walletOpened(bool)), q, SLOT(_k_openWalletDone(bool))); -+ connect(wallet.data(), SIGNAL(walletClosed()), q, SLOT(_k_walletClosed())); -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::removeDataFromCache(const WebFormList &formList) -+{ -+ if (!wallet) { -+ qWarning() << "NULL Wallet instance!"; -+ return; -+ } -+ -+ QVectorIterator formIt(formList); -+ while (formIt.hasNext()) { -+ wallet->removeEntry(walletKey(formIt.next())); -+ } -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::_k_openWalletDone(bool ok) -+{ -+ Q_ASSERT(wallet); -+ -+ if (ok && -+ (wallet->hasFolder(KWallet::Wallet::FormDataFolder()) || -+ wallet->createFolder(KWallet::Wallet::FormDataFolder())) && -+ wallet->setFolder(KWallet::Wallet::FormDataFolder())) { -+ -+ // Do pending fill requests... -+ if (!pendingFillRequests.isEmpty()) { -+ QList urlList; -+ QMutableHashIterator requestIt(pendingFillRequests); -+ while (requestIt.hasNext()) { -+ requestIt.next(); -+ WebEngineWallet::WebFormList list = requestIt.value().forms; -+ fillDataFromCache(list); -+ q->fillWebForm(requestIt.key(), list); -+ } -+ -+ pendingFillRequests.clear(); -+ } -+ -+ // Do pending save requests... -+ if (!pendingSaveRequests.isEmpty()) { -+ QListIterator keysIt(pendingSaveRequests.keys()); -+ while (keysIt.hasNext()) { -+ saveDataToCache(keysIt.next()); -+ } -+ } -+ -+ // Do pending remove requests... -+ if (!pendingRemoveRequests.isEmpty()) { -+ removeDataFromCache(pendingRemoveRequests); -+ pendingRemoveRequests.clear(); -+ } -+ } else { -+ // Delete the wallet if opening the wallet failed or we were unable -+ // to change to the folder we wanted to change to. -+ delete wallet.take(); -+ } -+} -+ -+void WebEngineWallet::WebEngineWalletPrivate::_k_walletClosed() -+{ -+ if (wallet) { -+ wallet.take()->deleteLater(); -+ } -+ -+ emit q->walletClosed(); -+} -+ -+WebEngineWallet::WebEngineWallet(QObject *parent, WId wid) -+ : QObject(parent), d(new WebEngineWalletPrivate(this)) -+{ -+ d->wid = wid; -+} -+ -+WebEngineWallet::~WebEngineWallet() -+{ -+ delete d; -+} -+ -+void WebEngineWallet::fillFormDataCallback(WebEnginePage* page, const WebEngineWallet::WebFormList& formsList) -+{ -+ QList urlList; -+ if (!formsList.isEmpty()) { -+ const QUrl url(page->url()); -+ if (d->pendingFillRequests.contains(url)) { -+ qWarning() << "Duplicate request rejected!"; -+ } else { -+ WebEngineWalletPrivate::FormsData data; -+ data.page = QPointer(page); -+ data.forms << formsList; -+ d->pendingFillRequests.insert(url, data); -+ urlList << url; -+ } -+ } -+ -+ if (!urlList.isEmpty()) { -+ fillFormDataFromCache(urlList); -+ } -+ -+} -+ -+void WebEngineWallet::fillFormData(WebEnginePage *page) -+{ -+ if (!page) return; -+ auto callback = [this, page](const WebFormList &forms){ -+ fillFormDataCallback(page, forms); -+ }; -+ d->withFormData(page, callback); -+} -+ -+static void createSaveKeyFor(WebEnginePage *page, QString *key) -+{ -+ QUrl pageUrl(page->url()); -+ pageUrl.setPassword(QString()); -+ -+ QString keyStr = pageUrl.toString(); -+ -+ *key = QString::number(qHash(keyStr), 16); -+} -+ -+void WebEngineWallet::saveFormData(WebEnginePage *page, bool ignorePasswordFields) -+{ -+ if (!page) { -+ return; -+ } -+ -+ QString key; -+ createSaveKeyFor(page, &key); -+ if (d->pendingSaveRequests.contains(key)) { -+ return; -+ } -+ -+ QUrl url = page->url(); -+ auto callback = [this, key, url](const WebFormList &list){saveFormDataCallback(key, url, list);}; -+ d->withFormData(page, callback, false, ignorePasswordFields); -+} -+ -+void WebEngineWallet::saveFormDataCallback(const QString &key, const QUrl& url, const WebEngineWallet::WebFormList& formsList) -+{ -+ -+ if (formsList.isEmpty()) { -+ return; -+ } -+ -+ WebFormList list(formsList); -+ -+ d->pendingSaveRequests.insert(key, list); -+ -+ QMutableVectorIterator it(list); -+ while (it.hasNext()) { -+ const WebForm form(it.next()); -+ if (hasCachedFormData(form)) { -+ it.remove(); -+ } -+ } -+ -+ if (list.isEmpty()) { -+ d->confirmSaveRequestOverwrites.insert(url); -+ saveFormDataToCache(key); -+ return; -+ } -+ -+ emit saveFormDataRequested(key, url); -+} -+ -+void WebEngineWallet::removeFormData(WebEnginePage *page) -+{ -+ if (page) { -+ auto callback = [this](const WebFormList &list){removeFormDataFromCache(list);}; -+ d->withFormData(page, callback); -+ } -+} -+ -+void WebEngineWallet::removeFormDataCallback(const WebFormList& list) -+{ -+ removeFormDataFromCache(list); -+} -+ -+ -+void WebEngineWallet::removeFormData(const WebFormList &forms) -+{ -+ d->pendingRemoveRequests << forms; -+ removeFormDataFromCache(forms); -+} -+ -+void WebEngineWallet::acceptSaveFormDataRequest(const QString &key) -+{ -+ saveFormDataToCache(key); -+} -+ -+void WebEngineWallet::rejectSaveFormDataRequest(const QString &key) -+{ -+ d->pendingSaveRequests.remove(key); -+} -+ -+void WebEngineWallet::fillWebForm(const QUrl &url, const WebEngineWallet::WebFormList &forms) -+{ -+ QPointer page = d->pendingFillRequests.value(url).page; -+ if (!page) { -+ return; -+ } -+ -+ QString script; -+ bool wasFilled = false; -+ -+ Q_FOREACH (const WebEngineWallet::WebForm &form, forms) { -+ Q_FOREACH (const WebEngineWallet::WebForm::WebField &field, form.fields) { -+ QString value = field.second; -+ value.replace(QL1C('\\'), QL1S("\\\\")); -+ script+= QString(s_javascriptFillInputFragment) -+ .arg(form.framePath) -+ .arg((form.name.isEmpty() ? form.index : form.name)) -+ .arg(field.first).arg(value); -+ } -+ } -+ if (!script.isEmpty()) { -+ wasFilled = true; -+ auto callback = [wasFilled, this](const QVariant &){emit fillFormRequestCompleted(wasFilled);}; -+ page.data()->runJavaScript(script, callback); -+ } -+} -+ -+WebEngineWallet::WebFormList WebEngineWallet::formsToFill(const QUrl &url) const -+{ -+ return d->pendingFillRequests.value(url).forms; -+} -+ -+WebEngineWallet::WebFormList WebEngineWallet::formsToSave(const QString &key) const -+{ -+ return d->pendingSaveRequests.value(key); -+} -+ -+bool WebEngineWallet::hasCachedFormData(const WebForm &form) const -+{ -+ return !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), -+ KWallet::Wallet::FormDataFolder(), -+ walletKey(form)); -+} -+ -+void WebEngineWallet::fillFormDataFromCache(const QList &urlList) -+{ -+ if (d->wallet) { -+ QListIterator urlIt(urlList); -+ while (urlIt.hasNext()) { -+ const QUrl url = urlIt.next(); -+ WebFormList list = formsToFill(url); -+ d->fillDataFromCache(list); -+ fillWebForm(url, list); -+ } -+ d->pendingFillRequests.clear(); -+ } -+ d->openWallet(); -+} -+ -+void WebEngineWallet::saveFormDataToCache(const QString &key) -+{ -+ if (d->wallet) { -+ d->saveDataToCache(key); -+ return; -+ } -+ d->openWallet(); -+} -+ -+void WebEngineWallet::removeFormDataFromCache(const WebFormList &forms) -+{ -+ if (d->wallet) { -+ d->removeDataFromCache(forms); -+ d->pendingRemoveRequests.clear(); -+ return; -+ } -+ d->openWallet(); -+} -+ -+#include "moc_webenginewallet.cpp" -diff --git a/webenginepart/src/webenginewallet.h b/webenginepart/src/webenginewallet.h -new file mode 100644 -index 0000000..2c3d65b ---- /dev/null -+++ b/webenginepart/src/webenginewallet.h -@@ -0,0 +1,305 @@ -+/* -+ * This file is part of the KDE project. -+ * -+ * Copyright (C) 2009 Dawit Alemayehu -+ * Copyright (C) 2018 Stefano Crocco -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public License -+ * along with this library; see the file COPYING.LIB. If not, write to -+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ * -+ */ -+#ifndef WEBENGINEWALLET_H -+#define WEBENGINEWALLET_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+class WebEnginePage; -+ -+class WebEngineWallet : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ -+ /** -+ * Holds data from a HTML <form> element. -+ */ -+ struct WebForm { -+ /** -+ * A typedef for storing the name and value attributes of HTML <input> -+ * elements. -+ */ -+ typedef QPair WebField; -+ -+ /** The URL the form was found at. */ -+ QUrl url; -+ /** The name attribute of the form. */ -+ QString name; -+ /** The position of the form on the web page, relative to other forms. */ -+ QString index; -+ /** The path of the frame the form belongs to relative to the toplevel window (in the javascript sense). -+ * -+ * This is stored as a string containing a javascript array (it is passed as is to javascript code, so no need to store it in C++ format -+ */ -+ QString framePath; -+ /** The name and value attributes of each input element in the form. */ -+ QVector fields; -+ }; -+ -+ /** -+ * A list of web forms -+ */ -+ typedef QVector WebFormList; -+ -+ /** -+ * Constructs a WebEngineWebWallet -+ * -+ * @p parent is usually the WebEnginePage this wallet is being used for. -+ * -+ * The @p wid parameter is used to tell the KWallet manager which window -+ * is requesting access to the wallet. -+ * -+ * @param parent the owner of this wallet -+ * @param wid the window ID of the window the web page will be -+ * embedded in -+ */ -+ explicit WebEngineWallet(QObject *parent = nullptr, WId wid = 0); -+ -+ /** -+ * Destructor -+ */ -+ virtual ~WebEngineWallet(); -+ -+ /** -+ * Attempts to save the form data from @p page and its children frames. -+ * -+ * You must connect to the @ref saveFormDataRequested signal and call either -+ * @ref rejectSaveFormDataRequest or @ref acceptSaveFormDataRequest signals -+ * in order to complete the save request. Otherwise, you request will simply -+ * be ignored. -+ * -+ * Note that this function is asynchronous, as it requires running javascript code -+ * on the page using @ref QWebEnginePage::runJavaScript. This function only requests -+ * for the form data to be saved when @ref QWebEnginePage::runJavaScript finishes. -+ * The actual saving is done by @ref saveFormDataCallback -+ */ -+ void saveFormData(WebEnginePage *page, bool ignorePasswordFields = false); -+ -+ /** -+ * Attempts to fill forms contained in @p page with cached data. -+ * -+ * Note that this function is asynchronous, as it requires running javascript code -+ * on the page using @ref QWebEnginePage::runJavaScript. This function only requests -+ * for the form data to be filled when @ref QWebEnginePage::runJavaScript finishes. -+ * The actual filling is done by @ref fillFormDataCallback -+ */ -+ void fillFormData(WebEnginePage *page); -+ -+ /** -+ * Removes the form data specified by @p forms from the persistent storage. -+ * -+ * Note that this function will remove all cached data for forms found in @p page. -+ * -+ * Note that this function is asynchronous, as it requires running javascript code -+ * on the page using @ref QWebEnginePage::runJavaScript. This function only requests -+ * for the form data to be removed when @ref QWebEnginePage::runJavaScript finishes. -+ * The actual removing is done by @ref removeFormDataCallback -+ */ -+ void removeFormData(WebEnginePage *page); -+ -+ /** -+ * Removes the form data specified by @p forms from the persistent storage. -+ * -+ * @see formsWithCachedData -+ */ -+ void removeFormData(const WebFormList &forms); -+ -+public Q_SLOTS: -+ /** -+ * Accepts the save form data request associated with @p key. -+ * -+ * The @p key parameter is the one sent through the @ref saveFormDataRequested -+ * signal. -+ * -+ * You must always call this function or @ref rejectSaveFormDataRequest in -+ * order to complete the save form data request. Otherwise, the request will -+ * simply be ignored. -+ * -+ * @see saveFormDataRequested. -+ */ -+ void acceptSaveFormDataRequest(const QString &key); -+ -+ /** -+ * Rejects the save form data request associated with @p key. -+ * -+ * The @p key parameter is the one sent through the @ref saveFormDataRequested -+ * signal. -+ * -+ * @see saveFormDataRequested. -+ */ -+ void rejectSaveFormDataRequest(const QString &key); -+ -+Q_SIGNALS: -+ /** -+ * This signal is emitted whenever a save form data request is received. -+ * -+ * Unless you connect to this signal and and call @ref acceptSaveFormDataRequest -+ * or @ref rejectSaveFormDataRequest slots, the save form data requested through -+ * @ref saveFormData will simply be ignored. -+ * -+ * @p key is a value that uniquely identifies the save request and @p url -+ * is the address for which the form data is being saved. -+ * -+ * @see acceptSaveFormDataRequest -+ * @see rejectSaveFormDataRequest -+ */ -+ void saveFormDataRequested(const QString &key, const QUrl &url); -+ -+ /** -+ * This signal is emitted whenever a save form data request is completed. -+ * -+ * @p ok will be set to true if the save form data request for @p url was -+ * completed successfully. -+ * -+ * @see saveFormDataRequested -+ */ -+ void saveFormDataCompleted(const QUrl &url, bool ok); -+ -+ /** -+ * This signal is emitted whenever a fill form data request is completed. -+ * -+ * @p ok will be set to true if any forms were successfully filled with -+ * cached data from the persistent storage. -+ * -+ * @see fillFormData -+ * @since 4.5 -+ */ -+ void fillFormRequestCompleted(bool ok); -+ -+ /** -+ * This signal is emitted whenever the current wallet is closed. -+ */ -+ void walletClosed(); -+ -+protected: -+ /** -+ * Returns a list of forms for @p url that are waiting to be filled. -+ * -+ * This function returns an empty list if there is no pending requests -+ * for filling forms associated with @p url. -+ */ -+ WebFormList formsToFill(const QUrl &url) const; -+ -+ /** -+ * Returns a list of for @p key that are waiting to be saved. -+ * -+ * This function returns an empty list if there are no pending requests -+ * for saving forms associated with @p key. -+ */ -+ WebFormList formsToSave(const QString &key) const; -+ -+ /** -+ * Returns forms to be removed from persistent storage. -+ */ -+ WebFormList formsToDelete() const; -+ -+ /** -+ * Returns true when there is data associated with @p form in the -+ * persistent storage. -+ */ -+ bool hasCachedFormData(const WebForm &form) const; -+ -+ /** -+ * Fills the web forms in frame that point to @p url with data from @p forms. -+ * -+ * @see fillFormDataFromCache. -+ */ -+ void fillWebForm(const QUrl &url, const WebFormList &forms); -+ -+ /** -+ * Fills form data from persistent storage. -+ * -+ * If you reimplement this function, call @ref formsToFill to obtain -+ * the list of forms pending to be filled. Once you fill the list with -+ * the cached data from the persistent storage, you must call @p fillWebForm -+ * to fill out the actual web forms. -+ * -+ * @see formsToFill -+ */ -+ void fillFormDataFromCache(const QList &list); -+ -+ /** -+ * Stores form data associated with @p key to a persistent storage. -+ * -+ * If you reimplement this function, call @ref formsToSave to obtain the -+ * list of form data pending to be saved to persistent storage. -+ * -+ *@see formsToSave -+ */ -+ void saveFormDataToCache(const QString &key); -+ -+ /** -+ * Removes all cached form data associated with @p forms from persistent storage. -+ * -+ * If you reimplement this function, call @ref formsToDelete to obtain the -+ * list of form data pending to be removed from persistent storage. -+ * -+ *@see formsToDelete -+ */ -+ void removeFormDataFromCache(const WebFormList &forms); -+ -+private: -+ -+ /** -+ * Callback used by @ref fillFormData to insert form data -+ * -+ * This function is called as a callback from @ref fillFormData after -+ * @ref QWebEnginePage::runJavaScript has finished -+ */ -+ void fillFormDataCallback(WebEnginePage *page, const WebFormList &formsList); -+ -+ /** -+ * Callback used by @ref saveFormData to save data -+ * -+ * This function is called as a callback from @ref saveFormData after -+ * @ref QWebEnginePage::runJavaScript has finished -+ */ -+ void saveFormDataCallback(const QString &key, const QUrl &url, const WebFormList &formslist); -+ -+ /** -+ * Callback used by @ref removeFormData to remove data -+ * -+ * This function is called as a callback from @ref removeFormData after -+ * @ref QWebEnginePage::runJavaScript has finished -+ */ -+ void removeFormDataCallback(const WebFormList &list); -+ -+private: -+ class WebEngineWalletPrivate; -+ friend class WebEngineWalletPrivate; -+ WebEngineWalletPrivate *const d; -+ -+ Q_PRIVATE_SLOT(d, void _k_openWalletDone(bool)) -+ Q_PRIVATE_SLOT(d, void _k_walletClosed()) -+}; -+ -+ -+#endif // WEBENGINEWALLET_H --- -cgit v0.11.2 - diff --git a/konqueror-17.12.3.tar.xz b/konqueror-17.12.3.tar.xz deleted file mode 100644 index b7c226a..0000000 --- a/konqueror-17.12.3.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1c020fa206511829556dd68840751bcc133861ef875a2eda2544f44aae101536 -size 7720068 diff --git a/konqueror-18.03.90.tar.xz b/konqueror-18.03.90.tar.xz new file mode 100644 index 0000000..d800d02 --- /dev/null +++ b/konqueror-18.03.90.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c71719ad955ecd3c435d5bdceedf0b14e9907b5c42d6526cc36e521c052111a +size 7725756 diff --git a/konqueror.changes b/konqueror.changes index 968df19..abd0491 100644 --- a/konqueror.changes +++ b/konqueror.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Fri Apr 06 07:09:49 CEST 2018 - lbeltrame@kde.org + +- Update to 18.03.90 + * New feature release + * For more details please see: + * https://www.kde.org/announcements/announce-applications-18.03.90.php +- Changes since 17.12.3: + * Load translation catalog webenginepart + * Include zlib also on build time + * Add back KWallet support to Konqueror + * Fix i18n usage +- Dropped patches, now upstream: + * add-kwallet-support-to-webengine.patch + ------------------------------------------------------------------- Thu Mar 08 23:52:07 CET 2018 - lbeltrame@kde.org diff --git a/konqueror.spec b/konqueror.spec index e514b34..cf962f2 100644 --- a/konqueror.spec +++ b/konqueror.spec @@ -19,7 +19,7 @@ %bcond_without lang Name: konqueror -Version: 17.12.3 +Version: 18.03.90 Release: 0 %define kf5_version 5.26.0 # Latest stable Applications (e.g. 17.08 in KA, but 17.11.80 in KUA) @@ -33,8 +33,6 @@ License: GPL-2.0-or-later Group: System/GUI/KDE Url: http://www.kde.org/ Source: %{name}-%{version}.tar.xz -# PATCH-FEATURE-UPSTREAM -Patch: add-kwallet-support-to-webengine.patch BuildRequires: extra-cmake-modules BuildRequires: kactivities5-devel >= 5.7.0 BuildRequires: karchive-devel >= 5.7.0 @@ -118,7 +116,6 @@ Development package for the konqueror libraries. %prep %setup -q -%patch -p1 sed -i 's|${CMAKE_CURRENT_SOURCE_DIR}/css|${CMAKE_CURRENT_SOURCE_DIR}/css ${CMAKE_BINARY_DIR}|g' settings/konqhtml/CMakeLists.txt %build