forked from pool/konqueror
bedfc8b344
- Add add-kwallet-support-to-webengine.patch to allow storing user names and passwords in kwallet when using the webenginepart OBS-URL: https://build.opensuse.org/request/show/582185 OBS-URL: https://build.opensuse.org/package/show/KDE:Applications/konqueror?expand=0&rev=59
1257 lines
44 KiB
Diff
1257 lines
44 KiB
Diff
From 56ea2a32d2f1d9f4e6c97b27080cf8144a932ee3 Mon Sep 17 00:00:00 2001
|
|
From: Stefano Crocco <stefano.crocco@alice.it>
|
|
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 <QWebEngineSettings>
|
|
#include <QWebEngineProfile>
|
|
|
|
@@ -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<WebEnginePart> m_part;
|
|
|
|
QScopedPointer<KPasswdServerClient> 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<QBoxLayout*>(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 <QWidget>
|
|
|
|
+
|
|
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 <adawit@kde.org>
|
|
+ * Copyright (C) 2018 Stefano Crocco <stefano.crocco@alice.it>
|
|
+ *
|
|
+ * 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 <KWallet>
|
|
+#include <QDebug>
|
|
+
|
|
+#include <QtCore/QSet>
|
|
+#include <QtCore/QHash>
|
|
+#include <QtCore/QFile>
|
|
+#include <QtCore/QPointer>
|
|
+#include <QtCore/QScopedPointer>
|
|
+#include <QJsonDocument>
|
|
+#include <qwindowdefs.h>
|
|
+
|
|
+#define QL1S(x) QLatin1String(x)
|
|
+#define QL1C(x) QLatin1Char(x)
|
|
+
|
|
+// Javascript used to extract/set data from <form> 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<WebEnginePage> page;
|
|
+ WebEngineWallet::WebFormList forms;
|
|
+ };
|
|
+
|
|
+ typedef std::function<void(const WebEngineWallet::WebFormList &)> 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<KWallet::Wallet> wallet;
|
|
+ WebEngineWallet::WebFormList pendingRemoveRequests;
|
|
+ QHash<QUrl, FormsData> pendingFillRequests;
|
|
+ QHash<QString, WebEngineWallet::WebFormList> pendingSaveRequests;
|
|
+ QSet<QUrl> 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<WebEngineWallet::WebForm::WebField> 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<QString, QString> cachedValues;
|
|
+ QMutableVectorIterator <WebForm> 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<WebEngineWallet::WebForm> formIt(list);
|
|
+
|
|
+ while (formIt.hasNext()) {
|
|
+ QMap<QString, QString> 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<WebEngineWallet::WebForm::WebField> 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<WebEngineWallet::WebForm::WebField> 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<WebForm> 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<QUrl> urlList;
|
|
+ QMutableHashIterator<QUrl, FormsData> 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<QString> 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<QUrl> 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<WebEnginePage>(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<WebForm> 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<WebEnginePage> 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<QUrl> &urlList)
|
|
+{
|
|
+ if (d->wallet) {
|
|
+ QListIterator<QUrl> 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 <adawit@kde.org>
|
|
+ * Copyright (C) 2018 Stefano Crocco <stefano.crocco@alice.it>
|
|
+ *
|
|
+ * 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 <QtCore/QObject>
|
|
+#include <QtCore/QString>
|
|
+#include <QtCore/QList>
|
|
+#include <QtCore/QPair>
|
|
+#include <QUrl>
|
|
+#include <QWidget>
|
|
+#include <QtCore/QtGlobal>
|
|
+
|
|
+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<QString, QString> 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<WebField> fields;
|
|
+ };
|
|
+
|
|
+ /**
|
|
+ * A list of web forms
|
|
+ */
|
|
+ typedef QVector<WebForm> 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<QUrl> &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
|
|
|