mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 02:36:34 +01:00
AutoFill: Initial port to QtWebEngine
There are still issues with completing forms in frames
This commit is contained in:
parent
a04efdc0be
commit
32a0db31b3
@ -24,7 +24,6 @@
|
|||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "webpage.h"
|
#include "webpage.h"
|
||||||
#include "qztools.h"
|
#include "qztools.h"
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "browserwindow.h"
|
#include "browserwindow.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "bookmarkstoolbar.h"
|
#include "bookmarkstoolbar.h"
|
||||||
#include "clearprivatedata.h"
|
#include "clearprivatedata.h"
|
||||||
#include "sourceviewer.h"
|
#include "sourceviewer.h"
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "autofill.h"
|
#include "autofill.h"
|
||||||
#include "networkmanagerproxy.h"
|
#include "networkmanagerproxy.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "pluginproxy.h"
|
#include "pluginproxy.h"
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
#include "browserwindow.h"
|
#include "browserwindow.h"
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "checkboxdialog.h"
|
#include "checkboxdialog.h"
|
||||||
#include "profilemanager.h"
|
#include "profilemanager.h"
|
||||||
#include "adblockmanager.h"
|
#include "adblockmanager.h"
|
||||||
@ -268,6 +267,7 @@ MainApplication::MainApplication(int &argc, char** argv)
|
|||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
m_plugins = new PluginProxy;
|
m_plugins = new PluginProxy;
|
||||||
|
m_autoFill = new AutoFill(this);
|
||||||
|
|
||||||
if (!noAddons)
|
if (!noAddons)
|
||||||
m_plugins->loadPlugins();
|
m_plugins->loadPlugins();
|
||||||
@ -503,9 +503,6 @@ Bookmarks* MainApplication::bookmarks()
|
|||||||
|
|
||||||
AutoFill* MainApplication::autoFill()
|
AutoFill* MainApplication::autoFill()
|
||||||
{
|
{
|
||||||
if (!m_autoFill) {
|
|
||||||
m_autoFill = new AutoFill(this);
|
|
||||||
}
|
|
||||||
return m_autoFill;
|
return m_autoFill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,14 +23,16 @@
|
|||||||
#include "popupwebview.h"
|
#include "popupwebview.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "autofillnotification.h"
|
#include "autofillnotification.h"
|
||||||
#include "pageformcompleter.h"
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "passwordmanager.h"
|
#include "passwordmanager.h"
|
||||||
#include "qztools.h"
|
#include "qztools.h"
|
||||||
|
#include "scripts.h"
|
||||||
|
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
#include <QWebEngineProfile>
|
||||||
|
#include <QWebEngineScriptCollection>
|
||||||
|
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
@ -40,6 +42,15 @@ AutoFill::AutoFill(QObject* parent)
|
|||||||
, m_isStoring(false)
|
, m_isStoring(false)
|
||||||
{
|
{
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
|
// Setup AutoFill userscript
|
||||||
|
QWebEngineScript script;
|
||||||
|
script.setName(QSL("_qupzilla_autofill"));
|
||||||
|
script.setInjectionPoint(QWebEngineScript::DocumentReady);
|
||||||
|
script.setWorldId(QWebEngineScript::MainWorld);
|
||||||
|
script.setRunsOnSubFrames(true);
|
||||||
|
script.setSourceCode(Scripts::setupFormObserver());
|
||||||
|
mApp->webProfile()->scripts()->insert(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordManager* AutoFill::passwordManager() const
|
PasswordManager* AutoFill::passwordManager() const
|
||||||
@ -166,75 +177,18 @@ void AutoFill::removeAllEntries()
|
|||||||
m_manager->removeAllEntries();
|
m_manager->removeAllEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If password was filled in the page, returns all saved passwords on this page
|
void AutoFill::saveForm(QWebEnginePage *page, const QUrl &frameUrl, const PageFormData &formData)
|
||||||
QVector<PasswordEntry> AutoFill::completeFrame(QWebEngineFrame* frame)
|
|
||||||
{
|
{
|
||||||
bool completed = false;
|
|
||||||
QVector<PasswordEntry> list;
|
|
||||||
|
|
||||||
if (!frame) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
const QUrl frameUrl = QzTools::frameUrl(frame);
|
|
||||||
if (!isStored(frameUrl)) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = getFormData(frameUrl);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!list.isEmpty()) {
|
|
||||||
const PasswordEntry entry = list.first();
|
|
||||||
|
|
||||||
PageFormCompleter completer;
|
|
||||||
completed = completer.completeFormData(frame, entry.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!completed) {
|
|
||||||
list.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingData)
|
|
||||||
{
|
|
||||||
Q_UNUSED(request)
|
|
||||||
Q_UNUSED(outgoingData)
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
// Don't save in private browsing
|
// Don't save in private browsing
|
||||||
if (mApp->isPrivate()) {
|
if (mApp->isPrivate() || !page)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
QWebEngineFrame* frame = qobject_cast<QWebEngineFrame*>(request.originatingObject());
|
WebView* webView = qobject_cast<WebView*>(page->view());
|
||||||
if (!frame) {
|
if (!webView)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
WebPage* webPage = qobject_cast<WebPage*>(frame->page());
|
if (!isStoringEnabled(frameUrl))
|
||||||
if (!webPage) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
WebView* webView = qobject_cast<WebView*>(webPage->view());
|
|
||||||
if (!webView) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QUrl frameUrl = QzTools::frameUrl(frame);
|
|
||||||
if (!isStoringEnabled(frameUrl)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormCompleter completer;
|
|
||||||
const PageFormData formData = completer.extractFormData(frame, outgoingData);
|
|
||||||
|
|
||||||
if (!formData.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PasswordEntry updateData;
|
PasswordEntry updateData;
|
||||||
|
|
||||||
@ -261,7 +215,24 @@ void AutoFill::post(const QNetworkRequest &request, const QByteArray &outgoingDa
|
|||||||
|
|
||||||
AutoFillNotification* aWidget = new AutoFillNotification(frameUrl, formData, updateData);
|
AutoFillNotification* aWidget = new AutoFillNotification(frameUrl, formData, updateData);
|
||||||
webView->addNotification(aWidget);
|
webView->addNotification(aWidget);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
// Returns all saved passwords on this page
|
||||||
|
QVector<PasswordEntry> AutoFill::completePage(QWebEnginePage *page, const QUrl &frameUrl)
|
||||||
|
{
|
||||||
|
QVector<PasswordEntry> list;
|
||||||
|
|
||||||
|
if (!page || !isStored(frameUrl))
|
||||||
|
return list;
|
||||||
|
|
||||||
|
list = getFormData(frameUrl);
|
||||||
|
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
const PasswordEntry entry = list.first();
|
||||||
|
page->runJavaScript(Scripts::completeFormData(entry.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray AutoFill::exportPasswords()
|
QByteArray AutoFill::exportPasswords()
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
#include "qzcommon.h"
|
#include "qzcommon.h"
|
||||||
|
|
||||||
class QUrl;
|
class QUrl;
|
||||||
class QWebEngineFrame;
|
class QWebEnginePage;
|
||||||
class QWebElement;
|
|
||||||
class QNetworkRequest;
|
class QNetworkRequest;
|
||||||
|
|
||||||
class BrowserWindow;
|
class BrowserWindow;
|
||||||
@ -32,6 +31,16 @@ class PasswordManager;
|
|||||||
struct PageFormData;
|
struct PageFormData;
|
||||||
struct PasswordEntry;
|
struct PasswordEntry;
|
||||||
|
|
||||||
|
struct PageFormData {
|
||||||
|
QString username;
|
||||||
|
QString password;
|
||||||
|
QByteArray postData;
|
||||||
|
|
||||||
|
bool isValid() const {
|
||||||
|
return !password.isEmpty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class QUPZILLA_EXPORT AutoFill : public QObject
|
class QUPZILLA_EXPORT AutoFill : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -60,8 +69,8 @@ public:
|
|||||||
void removeEntry(const PasswordEntry &entry);
|
void removeEntry(const PasswordEntry &entry);
|
||||||
void removeAllEntries();
|
void removeAllEntries();
|
||||||
|
|
||||||
void post(const QNetworkRequest &request, const QByteArray &outgoingData);
|
void saveForm(QWebEnginePage *page, const QUrl &frameUrl, const PageFormData &formData);
|
||||||
QVector<PasswordEntry> completeFrame(QWebEngineFrame *frame);
|
QVector<PasswordEntry> completePage(QWebEnginePage *page, const QUrl &frameUrl);
|
||||||
|
|
||||||
QByteArray exportPasswords();
|
QByteArray exportPasswords();
|
||||||
bool importPasswords(const QByteArray &data);
|
bool importPasswords(const QByteArray &data);
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include "qzcommon.h"
|
#include "qzcommon.h"
|
||||||
#include "animatedwidget.h"
|
#include "animatedwidget.h"
|
||||||
#include "pageformcompleter.h"
|
|
||||||
#include "passwordmanager.h"
|
#include "passwordmanager.h"
|
||||||
#include "autofill.h"
|
#include "autofill.h"
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
#include "autofillwidget.h"
|
#include "autofillwidget.h"
|
||||||
#include "ui_autofillwidget.h"
|
#include "ui_autofillwidget.h"
|
||||||
#include "pageformcompleter.h"
|
|
||||||
#include "autofill.h"
|
#include "autofill.h"
|
||||||
#include "qztools.h"
|
#include "qztools.h"
|
||||||
#include "webview.h"
|
#include "webview.h"
|
||||||
#include "webpage.h"
|
#include "webpage.h"
|
||||||
|
#include "scripts.h"
|
||||||
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
@ -67,9 +67,7 @@ void AutoFillWidget::loginToPage()
|
|||||||
|
|
||||||
if (ok && QzTools::containsIndex(m_data, index)) {
|
if (ok && QzTools::containsIndex(m_data, index)) {
|
||||||
const PasswordEntry entry = m_data.at(index);
|
const PasswordEntry entry = m_data.at(index);
|
||||||
|
m_view->page()->runJavaScript(Scripts::completeFormData(entry.data));
|
||||||
PageFormCompleter completer;
|
|
||||||
completer.completeFormData(m_view->page(), entry.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close();
|
close();
|
||||||
|
@ -1,284 +0,0 @@
|
|||||||
/* ============================================================
|
|
||||||
* QupZilla - WebKit based browser
|
|
||||||
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
* ============================================================ */
|
|
||||||
#include "pageformcompleter.h"
|
|
||||||
#include "qzregexp.h"
|
|
||||||
|
|
||||||
#include <QWebEnginePage>
|
|
||||||
#include <QUrlQuery>
|
|
||||||
|
|
||||||
PageFormCompleter::PageFormCompleter()
|
|
||||||
: m_page(0)
|
|
||||||
, m_frame(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormData PageFormCompleter::extractFormData(QWebEnginePage* page, const QByteArray &postData)
|
|
||||||
{
|
|
||||||
m_page = page;
|
|
||||||
return extractFormData(postData);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormData PageFormCompleter::extractFormData(QWebEngineFrame* frame, const QByteArray &postData)
|
|
||||||
{
|
|
||||||
m_frame = frame;
|
|
||||||
return extractFormData(postData);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageFormCompleter::completeFormData(QWebEnginePage* page, const QByteArray &data)
|
|
||||||
{
|
|
||||||
m_page = page;
|
|
||||||
return completeFormData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageFormCompleter::completeFormData(QWebEngineFrame* frame, const QByteArray &data)
|
|
||||||
{
|
|
||||||
m_frame = frame;
|
|
||||||
return completeFormData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormData PageFormCompleter::extractFormData(const QByteArray &postData) const
|
|
||||||
{
|
|
||||||
QString usernameValue;
|
|
||||||
QString passwordValue;
|
|
||||||
|
|
||||||
QByteArray data = convertWebKitFormBoundaryIfNecessary(postData);
|
|
||||||
PageFormData formData = {QString(), QString(), data};
|
|
||||||
|
|
||||||
if (data.isEmpty() || !data.contains('=')) {
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QueryItems queryItems = createQueryItems(data);
|
|
||||||
|
|
||||||
if (queryItems.isEmpty()) {
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
const QWebElementCollection allForms = getAllElementsFromPage("form");
|
|
||||||
|
|
||||||
// Find form that contains password value sent in data
|
|
||||||
foreach (const QWebElement &formElement, allForms) {
|
|
||||||
bool found = false;
|
|
||||||
const QWebElementCollection inputs = formElement.findAll("input[type=\"password\"]");
|
|
||||||
|
|
||||||
foreach (QWebElement inputElement, inputs) {
|
|
||||||
const QString passName = inputElement.attribute("name");
|
|
||||||
const QString passValue = inputElement.evaluateJavaScript("this.value").toString();
|
|
||||||
|
|
||||||
if (queryItemsContains(queryItems, passName, passValue)) {
|
|
||||||
// Set passwordValue if not empty (to make it possible extract forms without username field)
|
|
||||||
passwordValue = passValue;
|
|
||||||
|
|
||||||
const QueryItem item = findUsername(formElement);
|
|
||||||
if (queryItemsContains(queryItems, item.first, item.second)) {
|
|
||||||
usernameValue = item.second;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is necessary only to find password, as there may be form without username field
|
|
||||||
if (passwordValue.isEmpty()) {
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
formData.username = usernameValue;
|
|
||||||
formData.password = passwordValue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns if any data was actually filled in page
|
|
||||||
bool PageFormCompleter::completeFormData(const QByteArray &data) const
|
|
||||||
{
|
|
||||||
bool completed = false;
|
|
||||||
const QueryItems queryItems = createQueryItems(data);
|
|
||||||
|
|
||||||
// Input types that are being completed
|
|
||||||
QStringList inputTypes;
|
|
||||||
inputTypes << "text" << "password" << "email";
|
|
||||||
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
// Find all input elements in the page
|
|
||||||
const QWebElementCollection inputs = getAllElementsFromPage("input");
|
|
||||||
|
|
||||||
for (int i = 0; i < queryItems.count(); i++) {
|
|
||||||
const QString key = queryItems.at(i).first;
|
|
||||||
const QString value = queryItems.at(i).second;
|
|
||||||
|
|
||||||
for (int i = 0; i < inputs.count(); i++) {
|
|
||||||
QWebElement element = inputs.at(i);
|
|
||||||
const QString typeAttr = element.attribute("type");
|
|
||||||
|
|
||||||
if (!inputTypes.contains(typeAttr) && !typeAttr.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == element.attribute("name")) {
|
|
||||||
completed = true;
|
|
||||||
element.setAttribute("value", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageFormCompleter::queryItemsContains(const QueryItems &queryItems, const QString &attributeName,
|
|
||||||
const QString &attributeValue) const
|
|
||||||
{
|
|
||||||
if (attributeName.isEmpty() || attributeValue.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < queryItems.count(); i++) {
|
|
||||||
const QueryItem item = queryItems.at(i);
|
|
||||||
|
|
||||||
if (item.first == attributeName) {
|
|
||||||
return item.second == attributeValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray PageFormCompleter::convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const
|
|
||||||
{
|
|
||||||
/* Sometimes, data are passed in this format:
|
|
||||||
*
|
|
||||||
* ------WebKitFormBoundary0bBp3bFMdGwqanMp
|
|
||||||
* Content-Disposition: form-data; name="name-of-attribute"
|
|
||||||
*
|
|
||||||
* value-of-attribute
|
|
||||||
* ------WebKitFormBoundary0bBp3bFMdGwqanMp--
|
|
||||||
*
|
|
||||||
* So this function converts this format into name=value& format
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!data.contains(QByteArray("------WebKitFormBoundary"))) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray formatedData;
|
|
||||||
QzRegExp rx("name=\"(.*)------WebKitFormBoundary");
|
|
||||||
rx.setMinimal(true);
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
while ((pos = rx.indexIn(data, pos)) != -1) {
|
|
||||||
QString string = rx.cap(1);
|
|
||||||
pos += rx.matchedLength();
|
|
||||||
|
|
||||||
int endOfAttributeName = string.indexOf(QLatin1Char('"'));
|
|
||||||
if (endOfAttributeName == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString attrName = string.left(endOfAttributeName);
|
|
||||||
QString attrValue = string.mid(endOfAttributeName + 1).trimmed().remove(QLatin1Char('\n'));
|
|
||||||
|
|
||||||
if (attrName.isEmpty() || attrValue.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatedData.append(attrName + "=" + attrValue + "&");
|
|
||||||
}
|
|
||||||
|
|
||||||
return formatedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormCompleter::QueryItem PageFormCompleter::findUsername(const QWebElement &form) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(form)
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
// Try to find username (or email) field in the form.
|
|
||||||
QStringList selectors;
|
|
||||||
selectors << "input[type=\"text\"][name*=\"user\"]"
|
|
||||||
<< "input[type=\"text\"][name*=\"name\"]"
|
|
||||||
<< "input[type=\"text\"]"
|
|
||||||
<< "input[type=\"email\"]"
|
|
||||||
<< "input:not([type=\"hidden\"][type=\"password\"])";
|
|
||||||
|
|
||||||
foreach (const QString &selector, selectors) {
|
|
||||||
const QWebElementCollection inputs = form.findAll(selector);
|
|
||||||
foreach (QWebElement element, inputs) {
|
|
||||||
const QString name = element.attribute("name");
|
|
||||||
const QString value = element.evaluateJavaScript("this.value").toString();
|
|
||||||
|
|
||||||
if (!name.isEmpty() && !value.isEmpty()) {
|
|
||||||
QueryItem item;
|
|
||||||
item.first = name;
|
|
||||||
item.second = value;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return QueryItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
PageFormCompleter::QueryItems PageFormCompleter::createQueryItems(QByteArray data) const
|
|
||||||
{
|
|
||||||
// QUrlQuery/QUrl never encodes/decodes + and spaces
|
|
||||||
data.replace('+', ' ');
|
|
||||||
|
|
||||||
QUrlQuery query;
|
|
||||||
query.setQuery(data);
|
|
||||||
QueryItems arguments = query.queryItems(QUrl::FullyDecoded);
|
|
||||||
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
QWebElementCollection PageFormCompleter::getAllElementsFromPage(const QString &selector) const
|
|
||||||
{
|
|
||||||
QWebElementCollection list;
|
|
||||||
|
|
||||||
if (!m_page && !m_frame)
|
|
||||||
return list;
|
|
||||||
|
|
||||||
if (m_frame)
|
|
||||||
return m_frame->findAllElements(selector);
|
|
||||||
|
|
||||||
if (!m_page->mainFrame())
|
|
||||||
return list;
|
|
||||||
|
|
||||||
QList<QWebFrame*> frames;
|
|
||||||
frames.append(m_page->mainFrame());
|
|
||||||
|
|
||||||
while (!frames.isEmpty()) {
|
|
||||||
QWebFrame* frame = frames.takeFirst();
|
|
||||||
if (frame && !frame->documentElement().isNull()) {
|
|
||||||
list.append(frame->findAllElements(selector));
|
|
||||||
frames += frame->childFrames();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,73 +0,0 @@
|
|||||||
/* ============================================================
|
|
||||||
* QupZilla - WebKit based browser
|
|
||||||
* Copyright (C) 2013-2014 David Rosca <nowrep@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
* ============================================================ */
|
|
||||||
#ifndef PAGEFORMCOMPLETER_H
|
|
||||||
#define PAGEFORMCOMPLETER_H
|
|
||||||
|
|
||||||
#include <QPair>
|
|
||||||
#include <QString>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#include "qzcommon.h"
|
|
||||||
|
|
||||||
class QWebEnginePage;
|
|
||||||
class QWebEngineFrame;
|
|
||||||
class QWebElement;
|
|
||||||
class QWebElementCollection;
|
|
||||||
|
|
||||||
struct PageFormData {
|
|
||||||
QString username;
|
|
||||||
QString password;
|
|
||||||
QByteArray postData;
|
|
||||||
|
|
||||||
bool isValid() const {
|
|
||||||
return !password.isEmpty();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class QUPZILLA_EXPORT PageFormCompleter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit PageFormCompleter();
|
|
||||||
|
|
||||||
PageFormData extractFormData(QWebEnginePage* page, const QByteArray &postData);
|
|
||||||
PageFormData extractFormData(QWebEngineFrame* frame, const QByteArray &postData);
|
|
||||||
|
|
||||||
bool completeFormData(QWebEnginePage* page, const QByteArray &data);
|
|
||||||
bool completeFormData(QWebEngineFrame* frame, const QByteArray &data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef QPair<QString, QString> QueryItem;
|
|
||||||
typedef QList<QPair<QString, QString> > QueryItems;
|
|
||||||
|
|
||||||
PageFormData extractFormData(const QByteArray &postData) const;
|
|
||||||
bool completeFormData(const QByteArray &data) const;
|
|
||||||
|
|
||||||
bool queryItemsContains(const QueryItems &queryItems, const QString &attributeName,
|
|
||||||
const QString &attributeValue) const;
|
|
||||||
QByteArray convertWebKitFormBoundaryIfNecessary(const QByteArray &data) const;
|
|
||||||
QueryItem findUsername(const QWebElement &form) const;
|
|
||||||
QueryItems createQueryItems(QByteArray data) const;
|
|
||||||
#if QTWEBENGINE_DISABLED
|
|
||||||
QWebElementCollection getAllElementsFromPage(const QString &selector) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QWebEnginePage* m_page;
|
|
||||||
QWebEngineFrame* m_frame;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PAGEFORMCOMPLETER_H
|
|
@ -76,7 +76,6 @@ SOURCES += \
|
|||||||
autofill/autofillicon.cpp \
|
autofill/autofillicon.cpp \
|
||||||
autofill/autofillnotification.cpp \
|
autofill/autofillnotification.cpp \
|
||||||
autofill/autofillwidget.cpp \
|
autofill/autofillwidget.cpp \
|
||||||
autofill/pageformcompleter.cpp \
|
|
||||||
autofill/passwordbackends/databaseencryptedpasswordbackend.cpp \
|
autofill/passwordbackends/databaseencryptedpasswordbackend.cpp \
|
||||||
autofill/passwordbackends/databasepasswordbackend.cpp \
|
autofill/passwordbackends/databasepasswordbackend.cpp \
|
||||||
autofill/passwordbackends/passwordbackend.cpp \
|
autofill/passwordbackends/passwordbackend.cpp \
|
||||||
@ -237,7 +236,8 @@ SOURCES += \
|
|||||||
webtab/tabbedwebview.cpp \
|
webtab/tabbedwebview.cpp \
|
||||||
webtab/webtab.cpp \
|
webtab/webtab.cpp \
|
||||||
adblock/adblockmatcher.cpp \
|
adblock/adblockmatcher.cpp \
|
||||||
tools/scripts.cpp
|
tools/scripts.cpp \
|
||||||
|
webengine/javascript/autofilljsobject.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
3rdparty/ecwin7.h \
|
3rdparty/ecwin7.h \
|
||||||
@ -272,7 +272,6 @@ HEADERS += \
|
|||||||
autofill/autofillicon.h \
|
autofill/autofillicon.h \
|
||||||
autofill/autofillnotification.h \
|
autofill/autofillnotification.h \
|
||||||
autofill/autofillwidget.h \
|
autofill/autofillwidget.h \
|
||||||
autofill/pageformcompleter.h \
|
|
||||||
autofill/passwordbackends/databaseencryptedpasswordbackend.h \
|
autofill/passwordbackends/databaseencryptedpasswordbackend.h \
|
||||||
autofill/passwordbackends/databasepasswordbackend.h \
|
autofill/passwordbackends/databasepasswordbackend.h \
|
||||||
autofill/passwordbackends/passwordbackend.h \
|
autofill/passwordbackends/passwordbackend.h \
|
||||||
@ -326,7 +325,7 @@ HEADERS += \
|
|||||||
navigation/siteicon.h \
|
navigation/siteicon.h \
|
||||||
navigation/websearchbar.h \
|
navigation/websearchbar.h \
|
||||||
#network/cabundleupdater.h \
|
#network/cabundleupdater.h \
|
||||||
network/networkmanager.h \
|
#network/networkmanager.h \
|
||||||
network/networkmanagerproxy.h \
|
network/networkmanagerproxy.h \
|
||||||
network/networkproxyfactory.h \
|
network/networkproxyfactory.h \
|
||||||
network/pac/pacdatetime.h \
|
network/pac/pacdatetime.h \
|
||||||
@ -437,7 +436,8 @@ HEADERS += \
|
|||||||
webtab/tabbedwebview.h \
|
webtab/tabbedwebview.h \
|
||||||
webtab/webtab.h \
|
webtab/webtab.h \
|
||||||
adblock/adblockmatcher.h \
|
adblock/adblockmatcher.h \
|
||||||
tools/scripts.h
|
tools/scripts.h \
|
||||||
|
webengine/javascript/autofilljsobject.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
adblock/adblockaddsubscriptiondialog.ui \
|
adblock/adblockaddsubscriptiondialog.ui \
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "browserwindow.h"
|
#include "browserwindow.h"
|
||||||
#include "autofill.h"
|
#include "autofill.h"
|
||||||
#include "networkmanagerproxy.h"
|
#include "networkmanagerproxy.h"
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "editsearchengine.h"
|
#include "editsearchengine.h"
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "opensearchreader.h"
|
#include "opensearchreader.h"
|
||||||
#include "opensearchengine.h"
|
#include "opensearchengine.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -49,6 +49,57 @@ QString Scripts::setupWebChannel()
|
|||||||
return source.arg(QzTools::readAllFileContents(QSL(":/html/qwebchannel.js")));
|
return source.arg(QzTools::readAllFileContents(QSL(":/html/qwebchannel.js")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Scripts::setupFormObserver()
|
||||||
|
{
|
||||||
|
QString source = QL1S("(function() {"
|
||||||
|
"function findUsername(inputs) {"
|
||||||
|
" for (var i = 0; i < inputs.length; ++i)"
|
||||||
|
" if (inputs[i].type == 'text' && inputs[i].value.length && inputs[i].name.indexOf('user') != -1)"
|
||||||
|
" return inputs[i].value;"
|
||||||
|
" for (var i = 0; i < inputs.length; ++i)"
|
||||||
|
" if (inputs[i].type == 'text' && inputs[i].value.length && inputs[i].name.indexOf('name') != -1)"
|
||||||
|
" return inputs[i].value;"
|
||||||
|
" for (var i = 0; i < inputs.length; ++i)"
|
||||||
|
" if (inputs[i].type == 'text' && inputs[i].value.length)"
|
||||||
|
" return inputs[i].value;"
|
||||||
|
" for (var i = 0; i < inputs.length; ++i)"
|
||||||
|
" if (inputs[i].type == 'email' && inputs[i].value.length)"
|
||||||
|
" return inputs[i].value;"
|
||||||
|
" return '';"
|
||||||
|
"}"
|
||||||
|
"function registerForm(form) {"
|
||||||
|
" form.addEventListener('submit', function() {"
|
||||||
|
" var form = this;"
|
||||||
|
" var data = '';"
|
||||||
|
" var password = '';"
|
||||||
|
" var inputs = form.getElementsByTagName('input');"
|
||||||
|
" for (var i = 0; i < inputs.length; ++i) {"
|
||||||
|
" var input = inputs[i];"
|
||||||
|
" var type = input.type.toLowerCase();"
|
||||||
|
" if (type != 'text' && type != 'password' && type != 'email')"
|
||||||
|
" continue;"
|
||||||
|
" if (!password && type == 'password')"
|
||||||
|
" password = input.value;"
|
||||||
|
" data += encodeURIComponent(input.name);"
|
||||||
|
" data += '=';"
|
||||||
|
" data += encodeURIComponent(input.value);"
|
||||||
|
" data += '&';"
|
||||||
|
" }"
|
||||||
|
" if (!password)"
|
||||||
|
" return;"
|
||||||
|
" data = data.substring(0, data.length - 1);"
|
||||||
|
" var url = window.location.href;"
|
||||||
|
" var username = findUsername(inputs);"
|
||||||
|
" external.autoFill.formSubmitted(url, username, password, data);"
|
||||||
|
" }, true);"
|
||||||
|
"}"
|
||||||
|
"for (var i = 0; i < document.forms.length; ++i)"
|
||||||
|
" registerForm(document.forms[i]);"
|
||||||
|
"})()");
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
QString Scripts::setCss(const QString &css)
|
QString Scripts::setCss(const QString &css)
|
||||||
{
|
{
|
||||||
QString source = QL1S("(function() {"
|
QString source = QL1S("(function() {"
|
||||||
@ -94,3 +145,36 @@ QString Scripts::sendPostData(const QUrl &url, const QByteArray &data)
|
|||||||
|
|
||||||
return source.arg(url.toString(), values);
|
return source.arg(url.toString(), values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Scripts::completeFormData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QString source = QL1S("(function() {"
|
||||||
|
"var data = '%1'.split('&');"
|
||||||
|
"var inputs = [];"
|
||||||
|
"var frames = [window, window.frames];"
|
||||||
|
"for (var i = 0; i < frames.length; ++i) {"
|
||||||
|
" var finputs = frames[i].document.getElementsByTagName('input');"
|
||||||
|
" for (var j = 0; j < finputs.length; ++j) {"
|
||||||
|
" var type = finputs[j].type.toLowerCase();"
|
||||||
|
" if (type == 'text' || type == 'password' || type == 'email')"
|
||||||
|
" inputs.push(finputs[j]);"
|
||||||
|
" }"
|
||||||
|
"}"
|
||||||
|
"for (var i = 0; i < data.length; ++i) {"
|
||||||
|
" var pair = data[i].split('=');"
|
||||||
|
" if (pair.length != 2)"
|
||||||
|
" continue;"
|
||||||
|
" var key = decodeURIComponent(pair[0]);"
|
||||||
|
" var val = decodeURIComponent(pair[1]);"
|
||||||
|
" for (var j = 0; j < inputs.length; ++j) {"
|
||||||
|
" var input = inputs[j];"
|
||||||
|
" if (input.name == key)"
|
||||||
|
" input.value = val;"
|
||||||
|
" }"
|
||||||
|
"}"
|
||||||
|
"})()");
|
||||||
|
|
||||||
|
QString d = data;
|
||||||
|
d.replace(QL1S("'"), QL1S("\\'"));
|
||||||
|
return source.arg(d);
|
||||||
|
}
|
||||||
|
@ -29,8 +29,11 @@ class QUPZILLA_EXPORT Scripts
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static QString setupWebChannel();
|
static QString setupWebChannel();
|
||||||
|
static QString setupFormObserver();
|
||||||
|
|
||||||
static QString setCss(const QString &css);
|
static QString setCss(const QString &css);
|
||||||
static QString sendPostData(const QUrl &url, const QByteArray &data);
|
static QString sendPostData(const QUrl &url, const QByteArray &data);
|
||||||
|
static QString completeFormData(const QByteArray &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SCRIPTS_H
|
#endif // SCRIPTS_H
|
||||||
|
40
src/lib/webengine/javascript/autofilljsobject.cpp
Normal file
40
src/lib/webengine/javascript/autofilljsobject.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* QupZilla - QtWebEngine based browser
|
||||||
|
* Copyright (C) 2015 David Rosca <nowrep@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
#include "autofilljsobject.h"
|
||||||
|
#include "externaljsobject.h"
|
||||||
|
#include "mainapplication.h"
|
||||||
|
#include "autofill.h"
|
||||||
|
#include "webpage.h"
|
||||||
|
|
||||||
|
AutoFillJsObject::AutoFillJsObject(ExternalJsObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_jsObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoFillJsObject::formSubmitted(const QString &frameUrl, const QString &username, const QString &password, const QByteArray &data)
|
||||||
|
{
|
||||||
|
PageFormData formData;
|
||||||
|
formData.username = username;
|
||||||
|
formData.password = password;
|
||||||
|
formData.postData = data;
|
||||||
|
|
||||||
|
mApp->autoFill()->saveForm(m_jsObject->page(), QUrl(frameUrl), formData);
|
||||||
|
}
|
||||||
|
|
39
src/lib/webengine/javascript/autofilljsobject.h
Normal file
39
src/lib/webengine/javascript/autofilljsobject.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* QupZilla - QtWebEngine based browser
|
||||||
|
* Copyright (C) 2015 David Rosca <nowrep@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
#ifndef AUTOFILLJSOBJECT_H
|
||||||
|
#define AUTOFILLJSOBJECT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ExternalJsObject;
|
||||||
|
|
||||||
|
class AutoFillJsObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AutoFillJsObject(ExternalJsObject *parent);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void formSubmitted(const QString &frameUrl, const QString &username, const QString &password, const QByteArray &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ExternalJsObject *m_jsObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AUTOFILLJSOBJECT_H
|
@ -21,13 +21,20 @@
|
|||||||
#include "speeddial.h"
|
#include "speeddial.h"
|
||||||
#include "webpage.h"
|
#include "webpage.h"
|
||||||
#include "searchenginesmanager.h"
|
#include "searchenginesmanager.h"
|
||||||
|
#include "autofilljsobject.h"
|
||||||
|
|
||||||
ExternalJsObject::ExternalJsObject(WebPage *page)
|
ExternalJsObject::ExternalJsObject(WebPage *page)
|
||||||
: QObject(page)
|
: QObject(page)
|
||||||
, m_page(page)
|
, m_page(page)
|
||||||
|
, m_autoFill(new AutoFillJsObject(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPage *ExternalJsObject::page() const
|
||||||
|
{
|
||||||
|
return m_page;
|
||||||
|
}
|
||||||
|
|
||||||
void ExternalJsObject::AddSearchProvider(const QString &engineUrl)
|
void ExternalJsObject::AddSearchProvider(const QString &engineUrl)
|
||||||
{
|
{
|
||||||
mApp->searchEnginesManager()->addEngine(QUrl(engineUrl));
|
mApp->searchEnginesManager()->addEngine(QUrl(engineUrl));
|
||||||
@ -46,3 +53,8 @@ QObject *ExternalJsObject::speedDial() const
|
|||||||
|
|
||||||
return mApp->plugins()->speedDial();
|
return mApp->plugins()->speedDial();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject *ExternalJsObject::autoFill() const
|
||||||
|
{
|
||||||
|
return m_autoFill;
|
||||||
|
}
|
||||||
|
@ -21,24 +21,29 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class WebPage;
|
class WebPage;
|
||||||
|
class AutoFillJsObject;
|
||||||
|
|
||||||
class ExternalJsObject : public QObject
|
class ExternalJsObject : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QObject* speedDial READ speedDial CONSTANT)
|
Q_PROPERTY(QObject* speedDial READ speedDial CONSTANT)
|
||||||
|
Q_PROPERTY(QObject* autoFill READ autoFill CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ExternalJsObject(WebPage *page);
|
explicit ExternalJsObject(WebPage *page);
|
||||||
|
|
||||||
|
WebPage *page() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void AddSearchProvider(const QString &engineUrl);
|
void AddSearchProvider(const QString &engineUrl);
|
||||||
int IsSearchProviderInstalled(const QString &engineURL);
|
int IsSearchProviderInstalled(const QString &engineURL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QObject *speedDial() const;
|
QObject *speedDial() const;
|
||||||
|
QObject *autoFill() const;
|
||||||
|
|
||||||
WebPage *m_page;
|
WebPage *m_page;
|
||||||
|
AutoFillJsObject *m_autoFill;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EXTERNALJSOBJECT_H
|
#endif // EXTERNALJSOBJECT_H
|
||||||
|
@ -211,6 +211,9 @@ void WebPage::finished()
|
|||||||
|
|
||||||
// AdBlock
|
// AdBlock
|
||||||
cleanBlockedObjects();
|
cleanBlockedObjects();
|
||||||
|
|
||||||
|
// AutoFill
|
||||||
|
m_passwordEntries = mApp->autoFill()->completePage(this, url());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::watchedFileChanged(const QString &file)
|
void WebPage::watchedFileChanged(const QString &file)
|
||||||
@ -293,9 +296,17 @@ void WebPage::desktopServicesOpen(const QUrl &url)
|
|||||||
|
|
||||||
void WebPage::setupWebChannel()
|
void WebPage::setupWebChannel()
|
||||||
{
|
{
|
||||||
|
QWebChannel *old = webChannel();
|
||||||
|
const QString objectName = QSL("qz_object");
|
||||||
|
|
||||||
QWebChannel *channel = new QWebChannel(this);
|
QWebChannel *channel = new QWebChannel(this);
|
||||||
channel->registerObject(QSL("qz_object"), new ExternalJsObject(this));
|
channel->registerObject(QSL("qz_object"), new ExternalJsObject(this));
|
||||||
setWebChannel(channel);
|
setWebChannel(channel);
|
||||||
|
|
||||||
|
if (old) {
|
||||||
|
delete old->registeredObjects().value(objectName);
|
||||||
|
delete old;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::windowCloseRequested()
|
void WebPage::windowCloseRequested()
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "browserwindow.h"
|
#include "browserwindow.h"
|
||||||
#include "webpage.h"
|
#include "webpage.h"
|
||||||
#include "tabwidget.h"
|
#include "tabwidget.h"
|
||||||
#include "networkmanager.h"
|
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "tabbar.h"
|
#include "tabbar.h"
|
||||||
#include "webtab.h"
|
#include "webtab.h"
|
||||||
|
11
tests/form-iframe.html
Normal file
11
tests/form-iframe.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>Form completion test in iframe</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Form completion test in iframe</h2>
|
||||||
|
|
||||||
|
<iframe width="100%" height="80%" src="form.html"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user