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)
44 #define FORM_PARSING_JS "(function (){ \
46 var doc = (this.contentDocument ? this.contentDocument : document); \
47 var numForms = doc.forms.length; \
48 if (numForms > 0 ) { \
50 for (var i = 0; i < numForms; ++i) { \
51 var form = document.forms[i]; \
52 if (form.method.toLowerCase() != 'post') \
54 var formObject = new Object; \
55 formObject.name = form.name; \
56 formObject.index = i; \
57 var elements = new Array; \
58 var numElements = form.elements.length; \
59 for (var j = 0; j < numElements; ++j) { \
60 var e = form.elements[j]; \
61 var element = new Object; \
62 element.name = e.name; \
63 element.value = e.value; \
64 element.type = e.type; \
65 element.readonly = e.hasAttribute('readonly'); \
66 element.disabled = e.hasAttribute('disabled'); \
67 if (element.autocomplete != null) \
68 element.autocomplete = element.autocomplete.value; \
69 elements.push(element); \
71 formObject.elements = elements; \
72 forms.push(formObject); \
85 QString key = form.
url.toString(QUrl::RemoveQuery|QUrl::RemoveFragment);
93 list << frame->childFrames();
94 QListIterator<QWebFrame*> it(frame->childFrames());
95 while (it.hasNext()) {
102 return (frame->url().isEmpty() ? frame->baseUrl().resolved(frame->url()) : frame->url());
115 QWidget* widget = (page ? page->view() : qobject_cast<
QWidget*>(page));
116 while (widget && widget->parentWidget()) {
117 widget = widget->parentWidget();
119 return (widget ? widget->window() : 0);
127 QWeakPointer<QWebFrame> frame;
134 void saveDataToCache(
const QString &key);
135 void removeDataFromCache(
const WebFormList &formList);
139 void _k_openWalletDone(
bool);
140 void _k_walletClosed();
144 QScopedPointer<KWallet::Wallet> wallet;
146 QHash<KUrl, FormsData> pendingFillRequests;
147 QHash<QString, KWebWallet::WebFormList> pendingSaveRequests;
148 QSet<KUrl> confirmSaveRequestOverwrites;
156 KWebWallet::WebFormList KWebWallet::KWebWalletPrivate::parseFormData(QWebFrame *frame,
bool fillform,
bool ignorepasswd)
164 Q_FOREACH (
const QVariant &formVariant, results) {
165 QVariantMap map = formVariant.toMap();
168 form.
name = map[
QL1S(
"name")].toString();
169 form.
index = map[
QL1S(
"index")].toString();
170 bool formHasPasswords =
false;
171 const QVariantList elements = map[
QL1S(
"elements")].toList();
172 QList<KWebWallet::WebForm::WebField> inputFields;
173 Q_FOREACH (
const QVariant &element, elements) {
174 QVariantMap elementMap = element.toMap();
176 const QString value = (ignorepasswd ?
QString() : elementMap[
QL1S(
"value")].toString());
177 const QString type = elementMap[
QL1S(
"type")].toString();
178 const bool isPasswdInput = (type.compare(
QL1S(
"password"), Qt::CaseInsensitive) == 0);
179 const bool isTextInput = (type.compare(
QL1S(
"text"), Qt::CaseInsensitive) == 0);
180 const bool autoCompleteOff = (elementMap[
QL1S(
"autocomplete")].toString().compare(
QL1S(
"off"), Qt::CaseInsensitive) == 0);
183 if (!isPasswdInput && !isTextInput)
187 if (elementMap[
QL1S(
"disabled")].toBool())
189 if (fillform && elementMap[
QL1S(
"readonly")].toBool())
191 if (isPasswdInput && !fillform && value.isEmpty())
194 formHasPasswords =
true;
195 inputFields.append(qMakePair(name, value));
199 if (formHasPasswords && !fillform)
200 form.
fields = inputFields;
203 if ((fillform && q->hasCachedFormData(form)) || (!fillform && !form.
fields.isEmpty()))
212 kWarning(800) <<
"Unable to retrieve form data from wallet";
217 QMutableListIterator <WebForm> formIt (formList);
219 while (formIt.hasNext()) {
222 if (wallet->readMap(key, cachedValues) != 0) {
223 kWarning(800) <<
"Unable to read form data for key:" << key;
227 QMapIterator<QString, QString> valuesIt (cachedValues);
228 while (valuesIt.hasNext()) {
231 form.
fields << qMakePair(valuesIt.key(), valuesIt.value());
236 void KWebWallet::KWebWalletPrivate::saveDataToCache(
const QString &key)
239 if (!pendingSaveRequests.contains(key)) {
243 bool success =
false;
244 const QUrl url = pendingSaveRequests.value(key).first().url;
249 QListIterator<KWebWallet::WebForm> formIt (list);
251 while (formIt.hasNext()) {
254 const QString accessKey =
walletKey(form);
255 if (confirmSaveRequestOverwrites.contains(url)) {
256 confirmSaveRequestOverwrites.remove(url);
257 const int status = wallet->readMap(accessKey, storedValues);
258 if (status == 0 && storedValues.count()) {
259 QListIterator<KWebWallet::WebForm::WebField> fieldIt (form.
fields);
260 while (fieldIt.hasNext()) {
262 if (storedValues.contains(field.first) &&
263 storedValues.value(field.first) != field.second) {
264 emit q->saveFormDataRequested(key, url);
275 QListIterator<KWebWallet::WebForm::WebField> fieldIt (form.
fields);
276 while (fieldIt.hasNext()) {
278 values.insert(field.first, field.second);
281 if (wallet->writeMap(accessKey, values) == 0)
284 kWarning(800) <<
"Unable to write form data to wallet";
287 if (list.isEmpty() || count > 0)
290 pendingSaveRequests.remove(key);
292 kWarning(800) <<
"NULL KWallet instance!";
295 emit q->saveFormDataCompleted(url, success);
298 void KWebWallet::KWebWalletPrivate::openWallet()
300 if (!wallet.isNull()) {
307 if (wallet.isNull()) {
311 connect(wallet.data(), SIGNAL(walletOpened(
bool)), q, SLOT(_k_openWalletDone(
bool)));
312 connect(wallet.data(), SIGNAL(walletClosed()), q, SLOT(_k_walletClosed()));
316 void KWebWallet::KWebWalletPrivate::removeDataFromCache(
const WebFormList &formList)
319 kWarning(800) <<
"NULL KWallet instance!";
323 QListIterator<WebForm> formIt (formList);
324 while (formIt.hasNext())
325 wallet->removeEntry(
walletKey(formIt.next()));
328 void KWebWallet::KWebWalletPrivate::_k_openWalletDone(
bool ok)
338 if (!pendingFillRequests.isEmpty()) {
340 QMutableHashIterator<KUrl, FormsData> requestIt (pendingFillRequests);
341 while (requestIt.hasNext()) {
344 fillDataFromCache(list);
345 q->fillWebForm(requestIt.key(), list);
348 pendingFillRequests.clear();
352 if (!pendingSaveRequests.isEmpty()) {
353 QListIterator<QString> keysIt (pendingSaveRequests.keys());
354 while (keysIt.hasNext())
355 saveDataToCache(keysIt.next());
359 if (!pendingRemoveRequests.isEmpty()) {
360 removeDataFromCache(pendingRemoveRequests);
361 pendingRemoveRequests.clear();
366 delete wallet.take();
370 void KWebWallet::KWebWalletPrivate::_k_walletClosed()
373 wallet.take()->deleteLater();
375 emit q->walletClosed();
379 :
QObject(parent), d(new KWebWalletPrivate(this))
386 wid = widget->winId();
403 list << d->parseFormData(frame);
406 QList<QWebFrame*> childFrameList;
408 QListIterator <QWebFrame *> framesIt (childFrameList);
409 while (framesIt.hasNext()) {
410 list << d->parseFormData(framesIt.next());
425 if (!formsList.isEmpty()) {
427 if (d->pendingFillRequests.contains(url)) {
428 kWarning(800) <<
"Duplicate request rejected!";
430 KWebWalletPrivate::FormsData data;
431 data.frame = QWeakPointer<QWebFrame>(frame);
432 data.forms << formsList;
433 d->pendingFillRequests.insert(url, data);
439 QList<QWebFrame*> childFrameList;
441 QListIterator<QWebFrame*> frameIt (childFrameList);
442 while (frameIt.hasNext()) {
443 QWebFrame *childFrame = frameIt.next();
444 formsList = d->parseFormData(childFrame);
445 if (formsList.isEmpty())
447 const QUrl url (childFrame->url());
448 if (d->pendingFillRequests.contains(url)) {
449 kWarning(800) <<
"Duplicate request rejected!!!";
451 KWebWalletPrivate::FormsData data;
452 data.frame = QWeakPointer<QWebFrame>(childFrame);
453 data.forms << formsList;
454 d->pendingFillRequests.insert(url, data);
460 if (!urlList.isEmpty())
469 WebFormList list = d->parseFormData(frame,
false, ignorePasswordFields);
471 QList<QWebFrame*> childFrameList;
473 QListIterator<QWebFrame*> frameIt (childFrameList);
474 while (frameIt.hasNext())
475 list << d->parseFormData(frameIt.next(),
false, ignorePasswordFields);
481 const QString key = QString::number(
qHash(
urlForFrame(frame).toString() + frame->frameName()), 16);
482 const bool isAlreadyPending = d->pendingSaveRequests.contains(key);
483 d->pendingSaveRequests.insert(key, list);
485 if (isAlreadyPending)
488 for (
int i = 0 ; i < list.count(); ++i) {
493 if (list.isEmpty()) {
494 d->confirmSaveRequestOverwrites.insert(
urlForFrame(frame));
510 d->pendingRemoveRequests << forms;
521 d->pendingSaveRequests.remove(key);
526 QWeakPointer<QWebFrame> frame = d->pendingFillRequests.value(url).frame;
531 bool wasFilled =
false;
535 QString value = field.second;
536 value.replace(QLatin1Char(
'\\'), QLatin1String(
"\\\\"));
537 script += QString::fromLatin1(
"if (document.forms[\"%1\"].elements[\"%2\"]) document.forms[\"%1\"].elements[\"%2\"].value=\"%3\";\n")
539 .arg(field.first).arg(value);
543 if (!script.isEmpty()) {
545 frame.data()->evaluateJavaScript(script);
553 return d->pendingFillRequests.value(url).forms;
558 return d->pendingSaveRequests.value(key);
571 QListIterator<KUrl> urlIt (urlList);
572 while (urlIt.hasNext()) {
573 const KUrl url = urlIt.next();
575 d->fillDataFromCache(list);
578 d->pendingFillRequests.clear();
586 d->saveDataToCache(key);
595 d->removeDataFromCache(forms);
596 d->pendingRemoveRequests.clear();
602 #include "kwebwallet.moc"