28 #include <QtCore/QSet>
29 #include <QtCore/QHash>
30 #include <QtCore/QFile>
31 #include <QtCore/QWeakPointer>
32 #include <QtCore/QScopedPointer>
33 #include <QtWebKit/QWebPage>
34 #include <QtWebKit/QWebFrame>
35 #include <QtWebKit/QWebElement>
36 #include <QtWebKit/QWebElementCollection>
37 #include <qwindowdefs.h>
39 #define QL1S(x) QLatin1String(x)
40 #define QL1C(x) QLatin1Char(x)
43 #define FILLABLE_FORM_ELEMENT_EXTRACTOR_JS "(function (){ \
45 var formList = document.forms; \
46 if (formList.length > 0) { \
48 for (var i = 0; i < formList.length; ++i) { \
49 var inputList = formList[i].elements; \
50 if (inputList.length < 1) { \
53 var formObject = new Object; \
54 formObject.name = formList[i].name; \
55 if (typeof(formObject.name) != 'string') { \
56 formObject.name = String(formList[i].id); \
58 formObject.index = i; \
59 formObject.elements = new Array; \
60 for (var j = 0; j < inputList.length; ++j) { \
61 if (inputList[j].type != 'text' && inputList[j].type != 'email' && inputList[j].type != 'password') { \
64 if (inputList[j].disabled || inputList[j].autocomplete == 'off') { \
67 var element = new Object; \
68 element.name = inputList[j].name; \
69 if (typeof(element.name) != 'string' ) { \
70 element.name = String(inputList[j].id); \
72 element.value = String(inputList[j].value); \
73 element.type = String(inputList[j].type); \
74 element.readonly = Boolean(inputList[j].readOnly); \
75 formObject.elements.push(element); \
77 if (formObject.elements.length > 0) { \
78 forms.push(formObject); \
92 QString key = form.
url.toString(QUrl::RemoveQuery|QUrl::RemoveFragment);
100 list << frame->childFrames();
101 QListIterator<QWebFrame*> it(frame->childFrames());
102 while (it.hasNext()) {
109 return (frame->url().isEmpty() ? frame->baseUrl().resolved(frame->url()) : frame->url());
122 QWidget* widget = (page ? page->view() : qobject_cast<
QWidget*>(page));
123 while (widget && widget->parentWidget()) {
124 widget = widget->parentWidget();
126 return (widget ? widget->window() : 0);
134 QWeakPointer<QWebFrame> frame;
141 void saveDataToCache(
const QString &key);
142 void removeDataFromCache(
const WebFormList &formList);
146 void _k_openWalletDone(
bool);
147 void _k_walletClosed();
151 QScopedPointer<KWallet::Wallet> wallet;
158 KWebWallet::KWebWalletPrivate::KWebWalletPrivate(
KWebWallet *parent)
163 KWebWallet::WebFormList KWebWallet::KWebWalletPrivate::parseFormData(QWebFrame *frame,
bool fillform,
bool ignorepasswd)
170 const QVariantList results (result.toList());
171 Q_FOREACH (
const QVariant &formVariant, results) {
172 QVariantMap map = formVariant.toMap();
175 form.
name = map[
QL1S(
"name")].toString();
176 form.
index = map[
QL1S(
"index")].toString();
177 bool formHasPasswords =
false;
178 const QVariantList elements = map[
QL1S(
"elements")].toList();
180 Q_FOREACH (
const QVariant &element, elements) {
181 QVariantMap elementMap (element.toMap());
183 const QString value (ignorepasswd ?
QString() : elementMap[
QL1S(
"value")].toString());
184 if (
name.isEmpty()) {
187 if (fillform && elementMap[
QL1S(
"readonly")].toBool()) {
190 if (elementMap[
QL1S(
"type")].toString().compare(
QL1S(
"password"), Qt::CaseInsensitive) == 0) {
191 if (!fillform && value.isEmpty())
193 formHasPasswords =
true;
195 inputFields.append(qMakePair(name, value));
199 if (formHasPasswords || fillform) {
200 form.
fields = inputFields;
204 if ((fillform && q->hasCachedFormData(form)) || (!fillform && !form.
fields.isEmpty()))
214 kWarning(800) <<
"Unable to retrieve form data from wallet";
220 QMutableListIterator <WebForm> formIt (formList);
222 while (formIt.hasNext()) {
225 if (key != lastKey && wallet->readMap(key, cachedValues) != 0) {
226 kWarning(800) <<
"Unable to read form data for key:" << key;
230 for (
int i = 0, count = form.
fields.count(); i < count; ++i) {
231 form.
fields[i].second = cachedValues.value(form.
fields[i].first);
237 void KWebWallet::KWebWalletPrivate::saveDataToCache(
const QString &key)
240 if (!pendingSaveRequests.contains(key)) {
244 bool success =
false;
245 const QUrl url = pendingSaveRequests.value(key).first().url;
250 QListIterator<KWebWallet::WebForm> formIt (list);
252 while (formIt.hasNext()) {
256 if (confirmSaveRequestOverwrites.contains(url)) {
257 confirmSaveRequestOverwrites.remove(url);
258 const int status = wallet->readMap(accessKey, storedValues);
259 if (status == 0 && storedValues.count()) {
260 QListIterator<KWebWallet::WebForm::WebField> fieldIt (form.
fields);
261 while (fieldIt.hasNext()) {
263 if (storedValues.contains(field.first) &&
264 storedValues.value(field.first) != field.second) {
265 emit q->saveFormDataRequested(key, url);
276 QListIterator<KWebWallet::WebForm::WebField> fieldIt (form.
fields);
277 while (fieldIt.hasNext()) {
279 values.insert(field.first, field.second);
282 if (wallet->writeMap(accessKey, values) == 0)
285 kWarning(800) <<
"Unable to write form data to wallet";
288 if (list.isEmpty() || count > 0)
291 pendingSaveRequests.remove(key);
293 kWarning(800) <<
"NULL KWallet instance!";
296 emit q->saveFormDataCompleted(url, success);
299 void KWebWallet::KWebWalletPrivate::openWallet()
301 if (!wallet.isNull()) {
308 if (wallet.isNull()) {
312 connect(wallet.data(), SIGNAL(walletOpened(
bool)), q, SLOT(_k_openWalletDone(
bool)));
313 connect(wallet.data(), SIGNAL(walletClosed()), q, SLOT(_k_walletClosed()));
317 void KWebWallet::KWebWalletPrivate::removeDataFromCache(
const WebFormList &formList)
320 kWarning(800) <<
"NULL KWallet instance!";
324 QListIterator<WebForm> formIt (formList);
325 while (formIt.hasNext())
326 wallet->removeEntry(
walletKey(formIt.next()));
329 void KWebWallet::KWebWalletPrivate::_k_openWalletDone(
bool ok)
339 if (!pendingFillRequests.isEmpty()) {
341 QMutableHashIterator<KUrl, FormsData> requestIt (pendingFillRequests);
342 while (requestIt.hasNext()) {
345 fillDataFromCache(list);
346 q->fillWebForm(requestIt.key(), list);
349 pendingFillRequests.clear();
353 if (!pendingSaveRequests.isEmpty()) {
354 QListIterator<QString> keysIt (pendingSaveRequests.keys());
355 while (keysIt.hasNext())
356 saveDataToCache(keysIt.next());
360 if (!pendingRemoveRequests.isEmpty()) {
361 removeDataFromCache(pendingRemoveRequests);
362 pendingRemoveRequests.clear();
367 delete wallet.take();
371 void KWebWallet::KWebWalletPrivate::_k_walletClosed()
374 wallet.take()->deleteLater();
376 emit q->walletClosed();
380 :
QObject(parent), d(new KWebWalletPrivate(this))
387 wid = widget->winId();
404 list << d->parseFormData(frame);
409 QListIterator <QWebFrame *> framesIt (childFrameList);
410 while (framesIt.hasNext()) {
411 list << d->parseFormData(framesIt.next());
426 if (!formsList.isEmpty()) {
428 if (d->pendingFillRequests.contains(url)) {
429 kWarning(800) <<
"Duplicate request rejected!";
431 KWebWalletPrivate::FormsData data;
432 data.frame = QWeakPointer<QWebFrame>(frame);
433 data.forms << formsList;
434 d->pendingFillRequests.insert(url, data);
442 QListIterator<QWebFrame*> frameIt (childFrameList);
443 while (frameIt.hasNext()) {
444 QWebFrame *childFrame = frameIt.next();
445 formsList = d->parseFormData(childFrame);
446 if (formsList.isEmpty())
448 const QUrl url (childFrame->url());
449 if (d->pendingFillRequests.contains(url)) {
450 kWarning(800) <<
"Duplicate request rejected!!!";
452 KWebWalletPrivate::FormsData data;
453 data.frame = QWeakPointer<QWebFrame>(childFrame);
454 data.forms << formsList;
455 d->pendingFillRequests.insert(url, data);
461 if (!urlList.isEmpty())
468 frameUrl.setPassword(
QString());
469 frameUrl.setPassword(
QString());
471 QString keyStr = frameUrl.toString();
472 if (!frame->frameName().isEmpty())
473 keyStr += frame->frameName();
475 *key = QString::number(
qHash(keyStr), 16);
485 if (d->pendingSaveRequests.contains(key))
488 WebFormList list = d->parseFormData(frame,
false, ignorePasswordFields);
492 QListIterator<QWebFrame*> frameIt (childFrameList);
493 while (frameIt.hasNext())
494 list << d->parseFormData(frameIt.next(),
false, ignorePasswordFields);
500 d->pendingSaveRequests.insert(key, list);
502 QMutableListIterator<WebForm> it (list);
503 while (it.hasNext()) {
504 const WebForm form (it.next());
509 if (list.isEmpty()) {
510 d->confirmSaveRequestOverwrites.insert(
urlForFrame(frame));
526 d->pendingRemoveRequests << forms;
537 d->pendingSaveRequests.remove(key);
542 QWeakPointer<QWebFrame> frame = d->pendingFillRequests.value(url).frame;
547 bool wasFilled =
false;
552 value.replace(
QL1C(
'\\'),
QL1S(
"\\\\"));
553 script += QString::fromLatin1(
"if (document.forms[\"%1\"].elements[\"%2\"]) document.forms[\"%1\"].elements[\"%2\"].value=\"%3\";\n")
555 .arg(field.first).arg(value);
559 if (!script.isEmpty()) {
561 frame.data()->evaluateJavaScript(script);
569 return d->pendingFillRequests.value(url).forms;
574 return d->pendingSaveRequests.value(key);
587 QListIterator<KUrl> urlIt (urlList);
588 while (urlIt.hasNext()) {
589 const KUrl url = urlIt.next();
591 d->fillDataFromCache(list);
594 d->pendingFillRequests.clear();
602 d->saveDataToCache(key);
611 d->removeDataFromCache(forms);
612 d->pendingRemoveRequests.clear();
618 #include "kwebwallet.moc"
void saveFormData(QWebFrame *frame, bool recursive=true, bool ignorePasswordFields=false)
Attempts to save the form data from frame and its children frames.
virtual void fillFormDataFromCache(const KUrl::List &list)
Fills form data from persistent storage.
const char * name(StandardAction id)
WebFormList formsToFill(const KUrl &url) const
Returns a list of forms for url that are waiting to be filled.
static QWidget * topLevelWindow(QObject *obj)
void fillWebForm(const KUrl &url, const WebFormList &forms)
Fills the web forms in frame that point to url with data from forms.
static Wallet * openWallet(const QString &name, WId w, OpenType ot=Synchronous)
virtual ~KWebWallet()
Destructor.
static void createSaveKeyFor(QWebFrame *frame, QString *key)
virtual void removeFormDataFromCache(const WebFormList &forms)
Removes all cached form data associated with forms from persistent storage.
KWebWallet(QObject *parent=0, WId wid=0)
Constructs a KWebWallet.
static void collectAllChildFrames(QWebFrame *frame, QList< QWebFrame * > &list)
static QUrl urlForFrame(QWebFrame *frame)
WebFormList formsToSave(const QString &key) const
Returns a list of for key that are waiting to be saved.
void acceptSaveFormDataRequest(const QString &key)
Accepts the save form data request associated with key.
void removeFormData(QWebFrame *frame, bool recursive)
Removes the form data specified by forms from the persistent storage.
QList< WebForm > WebFormList
A list of web forms.
virtual bool hasCachedFormData(const WebForm &form) const
Returns true when there is data associated with form in the persistent storage.
void saveFormDataRequested(const QString &key, const QUrl &url)
This signal is emitted whenever a save form data request is received.
void fillFormData(QWebFrame *frame, bool recursive=true)
Attempts to fill forms contained in frame with cached data.
static const QString FormDataFolder()
virtual void saveFormDataToCache(const QString &key)
Stores form data associated with key to a persistent storage.
uint qHash(const KPluginInfo &p)
WebFormList formsWithCachedData(QWebFrame *frame, bool recursive=true) const
Returns a list of forms in frame that have cached data in the peristent storage.
void rejectSaveFormDataRequest(const QString &key)
Rejects the save form data request associated with key.
static bool keyDoesNotExist(const QString &wallet, const QString &folder, const QString &key)
static const QString NetworkWallet()
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
#define FILLABLE_FORM_ELEMENT_EXTRACTOR_JS
void fillFormRequestCompleted(bool ok)
This signal is emitted whenever a fill form data request is completed.
friend class KWebWalletPrivate
A class that provides KDE wallet integration for QWebFrame.
QStringList list(const QString &fileClass)
static QString walletKey(KWebWallet::WebForm form)
Creates key used to store and retrieve form data.