File indexing completed on 2024-05-19 05:01:21

0001 /*
0002     This file is part of the KDE project.
0003 
0004     SPDX-FileCopyrightText: 2007 Trolltech ASA
0005     SPDX-FileCopyrightText: 2008-2010 Urs Wolfer <uwolfer @ kde.org>
0006     SPDX-FileCopyrightText: 2008 Laurent Montel <montel@kde.org>
0007     SPDX-FileCopyrightText: 2009 Dawit Alemayehu <adawit@kde.org>
0008     SPDX-FileCopyrightText: 2013 Allan Sandfeld Jensen <sandfeld@kde.org>
0009 
0010     SPDX-License-Identifier: LGPL-2.1-or-later
0011 */
0012 
0013 #include "webenginepart.h"
0014 #include "schemehandlers/kiohandler.h"
0015 #include "about/konq_aboutpage.h"
0016 
0017 #include <webenginepart_debug.h>
0018 
0019 //#include <QWebHistoryItem>
0020 #include <QWebEngineSettings>
0021 #include <QWebEngineProfile>
0022 #include <QUrlQuery>
0023 
0024 #include "webenginepart_ext.h"
0025 #include "webengineview.h"
0026 #include "webenginepage.h"
0027 #include "websslinfo.h"
0028 #include "webhistoryinterface.h"
0029 #include "webenginewallet.h"
0030 #include "schemehandlers/errorschemehandler.h"
0031 #include "webengineurlrequestinterceptor.h"
0032 #include "spellcheckermanager.h"
0033 #include "webenginepartdownloadmanager.h"
0034 #include "webenginepartcontrols.h"
0035 #include "profile.h"
0036 
0037 #include "ui/searchbar.h"
0038 #include "ui/passwordbar.h"
0039 #include "ui/featurepermissionbar.h"
0040 #include "settings/webenginesettings.h"
0041 #include "ui/credentialsdetailswidget.h"
0042 
0043 #include <kconfigwidgets_version.h>
0044 #include <KCodecAction>
0045 #include <KIO/Global>
0046 #include <KIO/MetaData>
0047 
0048 #include <KActionCollection>
0049 #include <KPluginMetaData>
0050 #include <KUrlLabel>
0051 #include <KMessageBox>
0052 #include <KStringHandler>
0053 #include <KAcceleratorManager>
0054 #include <KFileItem>
0055 #include <KMessageWidget>
0056 #include <KProtocolInfo>
0057 #include <KToggleAction>
0058 #include <KParts/StatusBarExtension>
0059 #include <KParts/GUIActivateEvent>
0060 #include <KLocalizedString>
0061 #include <KConfigGroup>
0062 #include <KSharedConfig>
0063 #include <KSslInfoDialog>
0064 #include <KProtocolManager>
0065 #include <KParts/PartActivateEvent>
0066 #include <KIO/ApplicationLauncherJob>
0067 
0068 #include <QFile>
0069 #include <QCoreApplication>
0070 #include <QVBoxLayout>
0071 #include <QDBusInterface>
0072 #include <QMenu>
0073 #include <QStatusBar>
0074 #include <QWebEngineScriptCollection>
0075 #include <QDir>
0076 #if QT_VERSION_MAJOR > 5
0077 #include <QWebEngineFindTextResult>
0078 #endif
0079 
0080 #include "utils.h"
0081 #include <kio_version.h>
0082 
0083 using namespace WebEngine;
0084 
0085 WebEnginePart::WebEnginePart(QWidget *parentWidget, QObject *parent,
0086                          const KPluginMetaData& metaData,
0087                          const QByteArray& cachedHistory, const QStringList& /*args*/)
0088 #if QT_VERSION_MAJOR < 6
0089             :KParts::ReadOnlyPart(parent),
0090 #else
0091             :KParts::ReadOnlyPart(parent, metaData),
0092 #endif
0093              m_emitOpenUrlNotify(true),
0094              m_walletData{false, false, false},
0095              m_doLoadFinishedActions(false),
0096              m_statusBarWalletLabel(nullptr),
0097              m_searchBar(nullptr),
0098              m_passwordBar(nullptr),
0099              m_wallet(nullptr),
0100              m_downloader(new WebEngineDownloaderExtension(this))
0101 {
0102     if (!WebEnginePartControls::self()->isReady()) {
0103         WebEnginePartControls::self()->setup(KonqWebEnginePart::Profile::defaultProfile());
0104     }
0105 
0106     connect(WebEnginePartControls::self(), &WebEnginePartControls::userAgentChanged, this, &WebEnginePart::reloadAfterUAChange);
0107 
0108 #if QT_VERSION_MAJOR < 6
0109     setMetaData(metaData);
0110 #endif
0111 
0112 #if 0
0113     // NOTE: If the application does not set its version number, we automatically
0114     // set it to KDE's version number so that the default user-agent string contains
0115     // proper application version number information. See QWebEnginePage::userAgentForUrl...
0116     if (QCoreApplication::applicationVersion().isEmpty())
0117         QCoreApplication::setApplicationVersion(QString("%1.%2.%3")
0118                                                 .arg(KDE::versionMajor())
0119                                                 .arg(KDE::versionMinor())
0120                                                 .arg(KDE::versionRelease()));
0121 #endif
0122     setXMLFile(QL1S("webenginepart.rc"));
0123 
0124     // Create this KPart's widget
0125     QWidget *mainWidget = new QWidget (parentWidget);
0126     mainWidget->setObjectName(QStringLiteral("webenginepart"));
0127 
0128     // Create the WebEngineView...
0129     m_webView = new WebEngineView (this, parentWidget);
0130 
0131     // Create the browser extension.
0132     m_browserExtension = new WebEngineNavigationExtension(this, cachedHistory);
0133 
0134     // Add status bar extension...
0135     m_statusBarExtension = new KParts::StatusBarExtension(this);
0136 
0137     // Add text and html extensions...
0138     new WebEngineTextExtension(this);
0139     new WebEngineHtmlExtension(this);
0140 
0141 
0142     // Layout the GUI...
0143     QVBoxLayout* l = new QVBoxLayout(mainWidget);
0144     l->setContentsMargins(0, 0, 0, 0);
0145     l->setSpacing(0);
0146     l->addWidget(m_webView);
0147 
0148     // Set the part's widget
0149     setWidget(mainWidget);
0150 
0151     // Set the web view as the focus object
0152     mainWidget->setFocusProxy(m_webView);
0153 
0154     // Connect the signals from the webview
0155     connect(m_webView, &QWebEngineView::titleChanged,
0156             this, &Part::setWindowCaption);
0157     connect(m_webView, &QWebEngineView::urlChanged,
0158             this, &WebEnginePart::slotUrlChanged);
0159     connect(m_webView, &QWebEngineView::loadFinished,
0160             this, &WebEnginePart::slotLoadFinished);
0161 
0162     // Init the QAction we are going to use...
0163     initActions();
0164 
0165     // Load plugins once we are fully ready
0166     setWallet(new WebEngineWallet(this, parentWidget ? parentWidget->window()->winId() : 0));
0167 
0168     setPage(page());
0169 }
0170 
0171 WebEnginePart::~WebEnginePart()
0172 {
0173 }
0174 
0175 void WebEnginePart::setPage(WebEnginePage* newPage)
0176 {
0177     WebEnginePage *oldPage = page();
0178     if (oldPage && oldPage != newPage) {
0179         m_webView->setPage(newPage);
0180         newPage->setParent(m_webView);
0181     }
0182     newPage->setPart(this);
0183     // Connect the signals from the page...
0184     connectWebEnginePageSignals(newPage);
0185 }
0186 
0187 WebEnginePage* WebEnginePart::page()
0188 {
0189     if (m_webView)
0190         return qobject_cast<WebEnginePage*>(m_webView->page());
0191     return nullptr;
0192 }
0193 
0194 const WebEnginePage* WebEnginePart::page() const
0195 {
0196     if (m_webView)
0197         return qobject_cast<const WebEnginePage*>(m_webView->page());
0198     return nullptr;
0199 }
0200 
0201 WebEnginePartDownloadManager * WebEnginePart::downloadManager()
0202 {
0203     return WebEnginePartControls::self()->downloadManager();
0204 }
0205 
0206 SpellCheckerManager * WebEnginePart::spellCheckerManager()
0207 {
0208     return WebEnginePartControls::self()->spellCheckerManager();
0209 }
0210 
0211 void WebEnginePart::initActions()
0212 {
0213     QAction *action = actionCollection()->addAction(KStandardAction::SaveAs, QLatin1String("saveDocument"), m_browserExtension, &WebEngineNavigationExtension::slotSaveDocument);
0214 
0215     action = new QAction(QIcon::fromTheme(QStringLiteral("document-save-as")), i18n("Save Full HTML Page As..."), this);
0216     actionCollection()->addAction(QStringLiteral("saveFullHtmlPage"), action);
0217     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::slotSaveFullHTMLPage);
0218 
0219     action = new QAction(QIcon::fromTheme(QStringLiteral("document-print-preview")), i18n("Print Preview"), this);
0220     actionCollection()->addAction(QStringLiteral("printPreview"), action);
0221     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::slotPrintPreview);
0222 
0223     action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18nc("zoom in action", "Zoom In"), this);
0224     actionCollection()->addAction(QStringLiteral("zoomIn"), action);
0225     actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL++")) << QKeySequence(QStringLiteral("CTRL+=")));
0226     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::zoomIn);
0227 
0228     action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18nc("zoom out action", "Zoom Out"), this);
0229     actionCollection()->addAction(QStringLiteral("zoomOut"), action);
0230     actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL+-")) << QKeySequence(QStringLiteral("CTRL+_")));
0231     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::zoomOut);
0232 
0233     action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-original")), i18nc("reset zoom action", "Actual Size"), this);
0234     actionCollection()->addAction(QStringLiteral("zoomNormal"), action);
0235     actionCollection()->setDefaultShortcut(action, QKeySequence(QStringLiteral("CTRL+0")));
0236     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::zoomNormal);
0237 
0238     action = new QAction(i18n("Zoom Text Only"), this);
0239     action->setCheckable(true);
0240     KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings");
0241     bool zoomTextOnly = cgHtml.readEntry("ZoomTextOnly", false);
0242     action->setChecked(zoomTextOnly);
0243     actionCollection()->addAction(QStringLiteral("zoomTextOnly"), action);
0244     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::toogleZoomTextOnly);
0245 
0246     action = new QAction(i18n("Zoom To DPI"), this);
0247     action->setCheckable(true);
0248     bool zoomToDPI = cgHtml.readEntry("ZoomToDPI", false);
0249     action->setChecked(zoomToDPI);
0250     actionCollection()->addAction(QStringLiteral("zoomToDPI"), action);
0251     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::toogleZoomToDPI);
0252 
0253 
0254     action = KStandardAction::create(KStandardAction::SelectAll, m_browserExtension, &WebEngineNavigationExtension::slotSelectAll,
0255                                      actionCollection());
0256     action->setShortcutContext(Qt::WidgetShortcut);
0257     m_webView->addAction(action);
0258 
0259     KCodecAction *codecAction = new KCodecAction( QIcon::fromTheme(QStringLiteral("character-set")), i18n( "Set &Encoding" ), this, true );
0260     actionCollection()->addAction( QStringLiteral("setEncoding"), codecAction );
0261     connect(codecAction, &KCodecAction::codecNameTriggered, this, &WebEnginePart::slotSetTextEncoding);
0262     action = new QAction(i18n("View Do&cument Source"), this);
0263     actionCollection()->addAction(QStringLiteral("viewDocumentSource"), action);
0264     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_U));
0265     connect(action, &QAction::triggered, m_browserExtension, &WebEngineNavigationExtension::slotViewDocumentSource);
0266 
0267     action = new QAction(i18nc("Secure Sockets Layer", "SSL"), this);
0268     actionCollection()->addAction(QStringLiteral("security"), action);
0269     connect(action, &QAction::triggered, this, &WebEnginePart::slotShowSecurity);
0270 
0271     action = KStandardAction::create(KStandardAction::Find, this,
0272                                      &WebEnginePart::slotShowSearchBar, actionCollection());
0273     action->setWhatsThis(i18nc("find action \"whats this\" text", "<h3>Find text</h3>"
0274                               "Shows a dialog that allows you to find text on the displayed page."));
0275 
0276     createWalletActions();
0277 }
0278 
0279 void WebEnginePart::updateActions()
0280 {
0281     m_browserExtension->updateActions();
0282 
0283     auto enableActionIf = [this](const QString &name, bool enable) {
0284         QAction* action = actionCollection()->action(name);
0285         if (action) {
0286             action->setEnabled(enable);
0287         }
0288     };
0289 
0290     const QString protocol (url().scheme());
0291     bool saveEnabled = protocol != QL1S("about") && protocol != QL1S("error") && protocol != QL1S("konq");
0292 
0293     enableActionIf(QL1S("saveDocument"), saveEnabled);
0294     enableActionIf(QL1S("saveFullHtmlPage"), saveEnabled);
0295     enableActionIf(QL1S("printPreview"), m_browserExtension->isActionEnabled("print"));
0296 }
0297 
0298 void WebEnginePart::connectWebEnginePageSignals(WebEnginePage* page)
0299 {
0300     if (!page)
0301         return;
0302 
0303     connect(page, &QWebEnginePage::loadStarted, this, &WebEnginePart::slotLoadStarted);
0304     connect(page, &WebEnginePage::loadAborted, this, &WebEnginePart::slotLoadAborted);
0305     connect(page, &QWebEnginePage::linkHovered, this, &WebEnginePart::slotLinkHovered);
0306     connect(page, &QWebEnginePage::windowCloseRequested, this, &WebEnginePart::slotWindowCloseRequested);
0307     connect(page, &QWebEnginePage::loadProgress, m_browserExtension, &KParts::NavigationExtension::loadingProgress);
0308     connect(page, &QWebEnginePage::selectionChanged, m_browserExtension, &WebEngineNavigationExtension::updateEditActions);
0309 //    connect(m_browserExtension, SIGNAL(saveUrl(QUrl)),
0310 //            page, SLOT(downloadUrl(QUrl)));
0311 
0312     connect(page, &QWebEnginePage::iconUrlChanged, [page, this](const QUrl& url) {
0313         if (WebEngineSettings::self()->favIconsEnabled()
0314             && !page->profile()->isOffTheRecord()){
0315                 emit m_browserExtension->setIconUrl(url);
0316         }
0317     });
0318 }
0319 
0320 void WebEnginePart::setWallet(WebEngineWallet* wallet)
0321 {
0322     if(m_wallet){
0323         disconnect(m_wallet, &WebEngineWallet::saveFormDataRequested,
0324                 this, &WebEnginePart::slotSaveFormDataRequested);
0325         disconnect(m_wallet, &WebEngineWallet::fillFormRequestCompleted,
0326                 this, &WebEnginePart::slotFillFormRequestCompleted);
0327         disconnect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::resetWallet);
0328         disconnect(m_wallet, &WebEngineWallet::formDetectionDone, this, &WebEnginePart::walletFinishedFormDetection);
0329         disconnect(m_wallet, &WebEngineWallet::saveFormDataCompleted, this, &WebEnginePart::slotWalletSavedForms);
0330         disconnect(m_wallet, &WebEngineWallet::walletOpened, this, &WebEnginePart::updateWalletActions);
0331     }
0332     m_wallet = wallet;
0333     if (m_wallet) {
0334         connect(m_wallet, &WebEngineWallet::saveFormDataRequested,
0335                 this, &WebEnginePart::slotSaveFormDataRequested);
0336         connect(m_wallet, &WebEngineWallet::fillFormRequestCompleted,
0337                 this, &WebEnginePart::slotFillFormRequestCompleted);
0338         connect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::resetWallet);
0339         connect(m_wallet, &WebEngineWallet::formDetectionDone, this, &WebEnginePart::walletFinishedFormDetection);
0340         connect(m_wallet, &WebEngineWallet::saveFormDataCompleted, this, &WebEnginePart::slotWalletSavedForms);
0341         connect(m_wallet, &WebEngineWallet::walletOpened, this, &WebEnginePart::updateWalletActions);
0342     }
0343 }
0344 
0345 WebEngineWallet* WebEnginePart::wallet() const
0346 {
0347     return m_wallet;
0348 }
0349 
0350 void WebEnginePart::attemptInstallKIOSchemeHandler(const QUrl& url)
0351 {
0352      if (KProtocolManager::defaultMimetype(url) == "text/html") { // man:, info:, etc.
0353         auto *prof = KonqWebEnginePart::Profile::defaultProfile();
0354         QByteArray scheme = url.scheme().toUtf8();
0355         //Qt complains about installing a scheme handler overriding the internal "about" scheme
0356         if (scheme != "about" && !prof->urlSchemeHandler(scheme)) {
0357             prof->installUrlSchemeHandler(scheme, new KIOHandler(prof));
0358         }
0359     }
0360 
0361 }
0362 
0363 bool WebEnginePart::openUrl(const QUrl& _u)
0364 {
0365     if (_u.isEmpty()) {
0366         return false;
0367     }
0368 
0369     QUrl u(_u);
0370 
0371     // If the URL given is a supported local protocol, e.g. "bookmark" but lacks
0372     // a path component, we set the path to "/" here so that the security context
0373     // will properly allow access to local resources.
0374     if (u.host().isEmpty() && u.path().isEmpty()
0375         && KProtocolInfo::protocolClass(u.scheme()) == QL1S(":local")) {
0376         u.setPath(QL1S("/"));
0377     }
0378 
0379     // Do not emit update history when url is typed in since the host
0380     // should handle that automatically itself.
0381     m_emitOpenUrlNotify = false;
0382 
0383     // Pointer to the page object...
0384     WebEnginePage* p = page();
0385     Q_ASSERT(p);
0386 
0387     BrowserArguments bargs (m_browserExtension->browserArguments());
0388     KParts::OpenUrlArguments args (arguments());
0389 
0390     if (!Utils::isBlankUrl(u)) {
0391         // Get the SSL information sent, if any...
0392         if (args.metaData().contains(QL1S("ssl_in_use"))) {
0393             WebSslInfo sslInfo;
0394             sslInfo.restoreFrom(KIO::MetaData(args.metaData()).toVariant());
0395             sslInfo.setUrl(u);
0396             p->setSslInfo(sslInfo);
0397         }
0398     }
0399 
0400     attemptInstallKIOSchemeHandler(u);
0401 
0402     // Set URL in KParts before emitting started; konq plugins rely on that.
0403     setUrl(u);
0404     m_doLoadFinishedActions = true;
0405     m_webView->loadUrl(u, args, bargs);
0406     return true;
0407 }
0408 
0409 
0410 bool WebEnginePart::closeUrl()
0411 {
0412     m_webView->triggerPageAction(QWebEnginePage::Stop);
0413     m_webView->stop();
0414     return true;
0415 }
0416 
0417 QWebEngineView* WebEnginePart::view() const
0418 {
0419     return m_webView;
0420 }
0421 
0422 bool WebEnginePart::isModified() const
0423 {
0424     //return m_webView->isModified();
0425     return false;
0426 }
0427 
0428 // QWebEngineProfile * WebEnginePart::profile() const
0429 // {
0430 //     return WebEnginePartControls::self()->profile();
0431 // }
0432 //
0433 
0434 void WebEnginePart::guiActivateEvent(KParts::GUIActivateEvent *event)
0435 {
0436     if (event && event->activated() && m_webView) {
0437         emit setWindowCaption(m_webView->title());
0438     }
0439 }
0440 
0441 bool WebEnginePart::openFile()
0442 {
0443     // never reached
0444     return false;
0445 }
0446 
0447 
0448 /// slots...
0449 
0450 void WebEnginePart::slotLoadStarted()
0451 {
0452     if(!Utils::isBlankUrl(url()) && url() != QUrl("konq:konqueror"))
0453     {
0454         emit started(nullptr);
0455     }
0456     updateActions();
0457 
0458     // If "NoEmitOpenUrlNotification" property is set to true, do not
0459     // emit the open url notification. Property is set by this part's
0460     // extension to prevent openUrl notification being sent when
0461     // handling history navigation requests (back/forward).
0462     const bool doNotEmitOpenUrl = property("NoEmitOpenUrlNotification").toBool();
0463     if (doNotEmitOpenUrl) {
0464         setProperty("NoEmitOpenUrlNotification", QVariant());
0465     } else {
0466         if (m_emitOpenUrlNotify) {
0467             emit m_browserExtension->openUrlNotify();
0468         }
0469     }
0470     // Unless we go via openUrl again, the next time we are here we emit (e.g. after clicking on a link)
0471     m_emitOpenUrlNotify = true;
0472 }
0473 
0474 void WebEnginePart::slotLoadFinished (bool ok)
0475 {
0476     if (!ok || !m_doLoadFinishedActions)
0477         return;
0478 
0479     resetWallet();
0480     m_doLoadFinishedActions = false;
0481 
0482     // If the document contains no <title> tag, then set it to the current url.
0483     if (m_webView->title().trimmed().isEmpty()) {
0484         // If the document title is empty, then set it to the current url
0485         const QUrl url (m_webView->url());
0486         const QString caption (url.toString((QUrl::RemoveQuery|QUrl::RemoveFragment)));
0487         emit setWindowCaption(caption);
0488 
0489         // The urlChanged signal is emitted if and only if the main frame
0490         // receives the title of the page so we manually invoke the slot as a
0491         // work around here for pages that do not contain it, such as text
0492         // documents...
0493         slotUrlChanged(url);
0494     }
0495 
0496     if (m_wallet) {
0497         m_wallet->detectAndFillPageForms(page());
0498     }
0499 
0500     auto callback = [this](const QVariant &res) {
0501         if (!res.isValid()) {
0502             return;
0503         }
0504         bool hasRefresh = res.toBool();
0505         emit hasRefresh ? completedWithPendingAction() : completed();
0506     };
0507     page()->runJavaScript("hasRefreshAttribute()", QWebEngineScript::ApplicationWorld, callback);
0508     updateActions();
0509 }
0510 
0511 void WebEnginePart::slotLoadAborted(const QUrl & url)
0512 {
0513     closeUrl();
0514     m_doLoadFinishedActions = false;
0515     if (url.isValid())
0516         emit m_browserExtension->openUrlRequest(url);
0517     else
0518         setUrl(m_webView->url());
0519 }
0520 
0521 void WebEnginePart::slotUrlChanged(const QUrl& url)
0522 {
0523     // Ignore if empty
0524     if (url.isEmpty())
0525         return;
0526 
0527     // Ignore if error url
0528     if (url.scheme() == QL1S("error"))
0529         return;
0530 
0531     const QUrl u (url);
0532 
0533     // Ignore if url has not changed!
0534     if (this->url() == u)
0535       return;
0536 
0537     m_doLoadFinishedActions = true;
0538     setUrl(u);
0539 
0540     // Do not update the location bar with about:blank
0541     if (!Utils::isBlankUrl(url)) {
0542         //qCDebug(WEBENGINEPART_LOG) << "Setting location bar to" << u.prettyUrl() << "current URL:" << this->url();
0543         emit m_browserExtension->setLocationBarUrl(u.toDisplayString());
0544     }
0545 }
0546 
0547 void WebEnginePart::slotShowSecurity()
0548 {
0549     if (!page())
0550         return;
0551 
0552     const WebSslInfo& sslInfo = page()->sslInfo();
0553     if (!sslInfo.isValid()) {
0554         KMessageBox::information(nullptr, i18n("The SSL information for this site "
0555                                     "appears to be corrupt."),
0556                             i18nc("Secure Sockets Layer", "SSL"));
0557         return;
0558     }
0559 
0560     KSslInfoDialog *dlg = new KSslInfoDialog (widget());
0561     dlg->setSslInfo(sslInfo.certificateChain(),
0562                     sslInfo.peerAddress().toString(),
0563                     url().host(),
0564                     sslInfo.protocol(),
0565                     sslInfo.ciphers(),
0566                     sslInfo.usedChiperBits(),
0567                     sslInfo.supportedChiperBits(),
0568                     KSslInfoDialog::certificateErrorsFromString(sslInfo.certificateErrors()));
0569 
0570     dlg->open();
0571 }
0572 
0573 #if 0
0574 void WebEnginePart::slotSaveFrameState(QWebFrame *frame, QWebHistoryItem *item)
0575 {
0576     if (!frame || !item) {
0577         return;
0578     }
0579 
0580     // Handle actions that apply only to the mainframe...
0581     if (frame == view()->page()->mainFrame()) {
0582     }
0583 
0584     // For some reason, QtWebEngine PORTING_TODO does not restore scroll position when
0585     // QWebHistory is restored from persistent storage. Therefore, we
0586     // preserve that information and restore it as needed. See
0587     // slotRestoreFrameState.
0588     const QPoint scrollPos (frame->scrollPosition());
0589     if (!scrollPos.isNull()) {
0590         // qCDebug(WEBENGINEPART_LOG) << "Saving scroll position:" << scrollPos;
0591         item->setUserData(scrollPos);
0592     }
0593 }
0594 #endif
0595 
0596 #if 0
0597 void WebEnginePart::slotRestoreFrameState(QWebFrame *frame)
0598 {
0599     QWebEnginePage* page = (frame ? frame->page() : 0);
0600     QWebHistory* history = (page ? page->history() : 0);
0601 
0602     // No history item...
0603     if (!history || history->count() < 1)
0604         return;
0605 
0606     QWebHistoryItem currentHistoryItem (history->currentItem());
0607 
0608     // Update the scroll position if needed. See comment in slotSaveFrameState above.
0609     if (frame->baseUrl().resolved(frame->url()) == currentHistoryItem.url()) {
0610         const QPoint currentPos (frame->scrollPosition());
0611         const QPoint desiredPos (currentHistoryItem.userData().toPoint());
0612         if (currentPos.isNull() && !desiredPos.isNull()) {
0613             frame->setScrollPosition(desiredPos);
0614         }
0615     }
0616 }
0617 #endif
0618 
0619 void WebEnginePart::slotLinkHovered(const QString& _link)
0620 {
0621     QString message;
0622 
0623     if (_link.isEmpty()) {
0624         message = QL1S("");
0625         emit m_browserExtension->mouseOverInfo(KFileItem());
0626     } else {
0627         QUrl linkUrl (_link);
0628         const QString scheme = linkUrl.scheme();
0629 
0630         // Protect the user against URL spoofing!
0631         linkUrl.setUserName(QString());
0632         const QString link (linkUrl.toString());
0633 
0634         if (scheme == QL1S("mailto")) {
0635             message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", "Email: ");
0636 
0637             // Workaround: for QUrl's parsing deficiencies of "mailto:foo@bar.com".
0638             if (!linkUrl.hasQuery())
0639               linkUrl = QUrl(scheme + '?' + linkUrl.path());
0640 
0641             QMap<QString, QStringList> fields;
0642             QUrlQuery query(linkUrl);
0643             QList<QPair<QString, QString> > queryItems = query.queryItems();
0644             const int count = queryItems.count();
0645 
0646             for(int i = 0; i < count; ++i) {
0647                 const QPair<QString, QString> queryItem (queryItems.at(i));
0648                 //qCDebug(WEBENGINEPART_LOG) << "query: " << queryItem.first << queryItem.second;
0649                 if (queryItem.first.contains(QL1C('@')) && queryItem.second.isEmpty())
0650                     fields[QStringLiteral("to")] << queryItem.first;
0651                 if (QString::compare(queryItem.first, QL1S("to"), Qt::CaseInsensitive) == 0)
0652                     fields[QStringLiteral("to")] << queryItem.second;
0653                 if (QString::compare(queryItem.first, QL1S("cc"), Qt::CaseInsensitive) == 0)
0654                     fields[QStringLiteral("cc")] << queryItem.second;
0655                 if (QString::compare(queryItem.first, QL1S("bcc"), Qt::CaseInsensitive) == 0)
0656                     fields[QStringLiteral("bcc")] << queryItem.second;
0657                 if (QString::compare(queryItem.first, QL1S("subject"), Qt::CaseInsensitive) == 0)
0658                     fields[QStringLiteral("subject")] << queryItem.second;
0659             }
0660 
0661             if (fields.contains(QL1S("to")))
0662                 message += fields.value(QL1S("to")).join(QL1S(", "));
0663             if (fields.contains(QL1S("cc")))
0664                 message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - CC: ") + fields.value(QL1S("cc")).join(QL1S(", "));
0665             if (fields.contains(QL1S("bcc")))
0666                 message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - BCC: ") + fields.value(QL1S("bcc")).join(QL1S(", "));
0667             if (fields.contains(QL1S("subject")))
0668                 message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - Subject: ") + fields.value(QL1S("subject")).join(QL1S(" "));
0669         } else if (scheme == QL1S("javascript")) {
0670             message = KStringHandler::rsqueeze(link, 150);
0671             if (link.startsWith(QL1S("javascript:window.open")))
0672                 message += i18n(" (In new window)");
0673         } else {
0674             message = link;
0675 #if 0
0676             QWebFrame* frame = page() ? page()->currentFrame() : 0;
0677             if (frame) {
0678                 QWebHitTestResult result = frame->hitTestContent(page()->view()->mapFromGlobal(QCursor::pos()));
0679                 QWebFrame* target = result.linkTargetFrame();
0680                 if (frame->parentFrame() && target == frame->parentFrame()) {
0681                     message += i18n(" (In parent frame)");
0682                 } else if (!target || target != frame) {
0683                     message += i18n(" (In new window)");
0684                 }
0685             }
0686 #endif
0687             KFileItem item (linkUrl, QString(), KFileItem::Unknown);
0688             emit m_browserExtension->mouseOverInfo(item);
0689         }
0690     }
0691 
0692     emit setStatusBarText(message);
0693 }
0694 
0695 void WebEnginePart::slotSearchForText(const QString &text, bool backward)
0696 {
0697     QWebEnginePage::FindFlags flags; // = QWebEnginePage::FindWrapsAroundDocument;
0698 
0699     if (backward)
0700         flags |= QWebEnginePage::FindBackward;
0701 
0702     if (m_searchBar->caseSensitive()) {
0703         flags |= QWebEnginePage::FindCaseSensitively;
0704     }
0705 
0706 #if QT_VERSION_MAJOR < 6
0707     auto callback = [this](bool found){m_searchBar->setFoundMatch(found);};
0708 #else
0709     auto callback = [this](const QWebEngineFindTextResult &res){m_searchBar->setFoundMatch(res.numberOfMatches() > 0);};
0710 #endif
0711     //qCDebug(WEBENGINEPART_LOG) << "search for text:" << text << ", backward ?" << backward;
0712     //TODO KF6: when dropping compatibility with KF5, see whether it's better to connect to the
0713     //QWebEnginePage::findTextFinished signal rather than using the callback
0714     page()->findText(text, flags, callback);
0715 }
0716 
0717 void WebEnginePart::slotShowSearchBar()
0718 {
0719     if (!m_searchBar) {
0720         // Create the search bar...
0721         m_searchBar = new SearchBar(widget());
0722         connect(m_searchBar, &SearchBar::searchTextChanged, this, &WebEnginePart::slotSearchForText);
0723 
0724         // This essentially duplicates the use of
0725         // KActionCollection::addAction(KStandardAction::StandardAction actionType, const QObject *receiver, const char *member)
0726         // with the Qt5 connect syntax.
0727         KStandardAction::create(KStandardAction::FindNext, m_searchBar, &SearchBar::findNext, actionCollection());
0728         KStandardAction::create(KStandardAction::FindPrev, m_searchBar, &SearchBar::findPrevious, actionCollection());
0729 
0730         QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout());
0731         if (lay) {
0732           lay->addWidget(m_searchBar);
0733         }
0734     }
0735     const QString text = m_webView->selectedText();
0736     m_searchBar->setSearchText(text.left(150));
0737 }
0738 
0739 void WebEnginePart::slotLinkMiddleOrCtrlClicked(const QUrl& linkUrl)
0740 {
0741     emit m_browserExtension->createNewWindow(linkUrl);
0742 }
0743 
0744 void WebEnginePart::slotSelectionClipboardUrlPasted(const QUrl& selectedUrl, const QString& searchText)
0745 {
0746     if (!WebEngineSettings::self()->isOpenMiddleClickEnabled())
0747         return;
0748 
0749     if (!searchText.isEmpty() &&
0750         KMessageBox::questionTwoActions(m_webView,
0751                                    i18n("<qt>Do you want to search for <b>%1</b>?</qt>", searchText),
0752                                    i18n("Internet Search"), KGuiItem(i18n("&Search"), QStringLiteral("edit-find")),
0753                                    KStandardGuiItem::cancel(), QStringLiteral("MiddleClickSearch")) != KMessageBox::PrimaryAction)
0754         return;
0755 
0756     emit m_browserExtension->openUrlRequest(selectedUrl);
0757 }
0758 
0759 void WebEnginePart::deleteStatusBarWalletLabel()
0760 {
0761     if (!m_statusBarWalletLabel) {
0762        return;
0763     }
0764     m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel);
0765     delete m_statusBarWalletLabel;
0766     m_statusBarWalletLabel = nullptr;
0767 }
0768 
0769 void WebEnginePart::resetWallet()
0770 {
0771     deleteStatusBarWalletLabel();
0772     updateWalletData({false, false, false});
0773     updateWalletActions();
0774 }
0775 
0776 void WebEnginePart::slotShowWalletMenu()
0777 {
0778     QMenu *menu = new QMenu(nullptr);
0779     auto addAction = [this, menu](const QString &name) {
0780         QAction *a = actionCollection()->action(name);
0781         if (a->isEnabled()) {
0782             menu->addAction(a);
0783         }
0784     };
0785     addAction("walletFillFormsNow");
0786     addAction("walletCacheFormsNow");
0787 
0788     addAction("walletCustomizeFields");
0789     addAction("walletRemoveCustomization");
0790     menu->addSeparator();
0791 
0792     addAction("walletDisablePasswordCaching");
0793     addAction("walletRemoveCachedData");
0794     menu->addSeparator();
0795 
0796     addAction("walletShowManager");
0797     addAction("walletCloseWallet");
0798 
0799     KAcceleratorManager::manage(menu);
0800     menu->popup(QCursor::pos());
0801 }
0802 
0803 void WebEnginePart::slotLaunchWalletManager()
0804 {
0805     const KService::Ptr kwalletManager = KService::serviceByDesktopName(QStringLiteral("org.kde.kwalletmanager5"));
0806     auto job = new KIO::ApplicationLauncherJob(kwalletManager);
0807     job->start();
0808 }
0809 
0810 void WebEnginePart::togglePasswordStorableState(bool on)
0811 {
0812     if (!m_webView) {
0813         return;
0814     }
0815     QString host = m_webView->url().host();
0816     if (on) {
0817         WebEngineSettings::self()->removeNonPasswordStorableSite(host);
0818     } else {
0819         WebEngineSettings::self()->addNonPasswordStorableSite(host);
0820     }
0821     updateWalletActions();
0822     updateWalletStatusBarIcon();
0823 }
0824 
0825 void WebEnginePart::slotRemoveCachedPasswords()
0826 {
0827     if (!m_wallet) {
0828         return;
0829     }
0830 
0831     m_wallet->removeFormData(page());
0832     updateWalletData(WalletData::HasCachedData, false);
0833 }
0834 
0835 void WebEnginePart::slotSetTextEncoding(const QString &codecName)
0836 {
0837     // FIXME: The code below that sets the text encoding has been reported not to work.
0838     if (!page())
0839         return;
0840 
0841     QWebEngineSettings *localSettings = page()->settings();
0842     if (!localSettings)
0843         return;
0844 
0845     qCDebug(WEBENGINEPART_LOG) << "Encoding: new=>" << localSettings->defaultTextEncoding() << ", old=>" << codecName;
0846 
0847     localSettings->setDefaultTextEncoding(codecName);
0848     page()->triggerAction(QWebEnginePage::Reload);
0849 }
0850 
0851 void WebEnginePart::slotSetStatusBarText(const QString& text)
0852 {
0853     const QString host (page() ? page()->url().host() : QString());
0854     if (WebEngineSettings::self()->windowStatusPolicy(host) == HtmlSettingsInterface::JSWindowStatusAllow)
0855         emit setStatusBarText(text);
0856 }
0857 
0858 void WebEnginePart::slotWindowCloseRequested()
0859 {
0860     emit m_browserExtension->requestFocus(this);
0861 #if 0
0862     if (KMessageBox::questionYesNo(m_webView,
0863                                    i18n("Close window?"), i18n("Confirmation Required"),
0864                                    KStandardGuiItem::close(), KStandardGuiItem::cancel())
0865         != KMessageBox::Yes)
0866         return;
0867 #endif
0868     this->deleteLater();
0869 }
0870 
0871 void WebEnginePart::slotShowFeaturePermissionBar(const QUrl &origin, QWebEnginePage::Feature feature)
0872 {
0873     auto findExistingBar = [origin, feature](FeaturePermissionBar *bar) {
0874         return bar->url() == origin && bar->feature() == feature;
0875     };
0876     auto found = std::find_if(m_permissionBars.constBegin(), m_permissionBars.constEnd(), findExistingBar);
0877     if (found != m_permissionBars.constEnd()) {
0878         return;
0879     }
0880     FeaturePermissionBar *bar = new FeaturePermissionBar(widget());
0881     m_permissionBars.append(bar);
0882     auto policyLambda = [this, bar](QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) {
0883         slotFeaturePolicyChosen(bar, feature, policy);
0884     };
0885     connect(bar, &FeaturePermissionBar::permissionPolicyChosen, this, policyLambda);
0886     connect(bar, &FeaturePermissionBar::done, this, [this, bar](){deleteFeaturePermissionBar(bar);});
0887     QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout());
0888     if (lay) {
0889         lay->insertWidget(0, bar);
0890     }
0891     bar->setUrl(origin);
0892     bar->setFeature(feature);
0893     bar->animatedShow();
0894 }
0895 
0896 void WebEnginePart::slotFeaturePolicyChosen(FeaturePermissionBar* bar, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy)
0897 {
0898     Q_ASSERT(bar && bar->feature() == feature);
0899     page()->setFeaturePermission(bar->url(), feature, policy);
0900 }
0901 
0902 void WebEnginePart::deleteFeaturePermissionBar(FeaturePermissionBar *bar)
0903 {
0904     m_permissionBars.removeOne(bar);
0905     bar->deleteLater();
0906 }
0907 
0908 void WebEnginePart::slotSaveFormDataRequested (const QString& key, const QUrl& url)
0909 {
0910     if (WebEngineSettings::self()->isNonPasswordStorableSite(url.host()))
0911         return;
0912 
0913     if (!WebEngineSettings::self()->askToSaveSitePassword())
0914         return;
0915 
0916     if (m_passwordBar && m_passwordBar->isVisible())
0917         return;
0918 
0919     if (!m_passwordBar) {
0920         m_passwordBar = new PasswordBar(widget());
0921         if (!m_wallet) {
0922             qCWarning(WEBENGINEPART_LOG) << "No m_wallet instance found! This should never happen!";
0923             return;
0924         }
0925         connect(m_passwordBar, &PasswordBar::saveFormDataAccepted,
0926                 m_wallet, &WebEngineWallet::acceptSaveFormDataRequest);
0927         connect(m_passwordBar, &PasswordBar::saveFormDataRejected,
0928                 m_wallet, &WebEngineWallet::rejectSaveFormDataRequest);
0929         connect(m_passwordBar, &PasswordBar::done, this, &WebEnginePart::slotSaveFormDataDone);
0930     }
0931 
0932     Q_ASSERT(m_passwordBar);
0933 
0934     m_passwordBar->setForms(m_wallet->pendingSaveData(key));
0935     m_passwordBar->setUrl(url);
0936     m_passwordBar->setRequestKey(key);
0937     m_passwordBar->setText(i18n("<html>Do you want %1 to remember the login "
0938                                 "information for <b>%2</b>?</html>",
0939                                 QCoreApplication::applicationName(),
0940                                 url.host()));
0941 
0942     QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout());
0943     if (lay) {
0944         lay->insertWidget(0, m_passwordBar);
0945     }
0946 
0947     m_passwordBar->animatedShow();
0948 }
0949 
0950 void WebEnginePart::slotSaveFormDataDone()
0951 {
0952     if (!m_passwordBar)
0953         return;
0954 
0955     QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout());
0956     if (lay)
0957         lay->removeWidget(m_passwordBar);
0958 }
0959 
0960 void WebEnginePart::updateWalletStatusBarIcon ()
0961 {
0962     if (m_walletData.hasForms) {
0963         if (m_statusBarWalletLabel) {
0964             m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel);
0965         } else {
0966             m_statusBarWalletLabel = new KUrlLabel(m_statusBarExtension->statusBar());
0967             m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
0968             m_statusBarWalletLabel->setUseCursor(false);
0969             connect(m_statusBarWalletLabel, QOverload<>::of(&KUrlLabel::leftClickedUrl), this, &WebEnginePart::slotLaunchWalletManager);
0970             connect(m_statusBarWalletLabel, QOverload<>::of(&KUrlLabel::rightClickedUrl), this, &WebEnginePart::slotShowWalletMenu);
0971         }
0972         QIcon icon = QIcon::fromTheme(m_walletData.hasCachedData ? QStringLiteral("wallet-open") : QStringLiteral("wallet-closed"));
0973         m_statusBarWalletLabel->setPixmap(icon.pixmap(QSize(16,16)));
0974         m_statusBarExtension->addStatusBarItem(m_statusBarWalletLabel, 0, false);
0975     } else if (m_statusBarWalletLabel) {
0976         deleteStatusBarWalletLabel();
0977     }
0978 }
0979 
0980 void WebEnginePart::slotFillFormRequestCompleted (bool ok)
0981 {
0982     updateWalletData(WalletData::HasCachedData, ok);
0983 }
0984 
0985 void WebEnginePart::exitFullScreen()
0986 {
0987     page()->triggerAction(QWebEnginePage::ExitFullScreen);
0988 }
0989 
0990 void WebEnginePart::walletFinishedFormDetection(const QUrl& url, bool found, bool autoFillableFound)
0991 {
0992     if (page() && page()->url() == url) {
0993         updateWalletData({found, autoFillableFound});
0994         updateWalletActions();
0995         updateWalletStatusBarIcon();
0996     }
0997 }
0998 
0999 void WebEnginePart::slotWalletSavedForms(const QUrl& url, bool success)
1000 {
1001     if (success && url == this->url()) {
1002         updateWalletData(WalletData::HasCachedData, true);
1003     }
1004 }
1005 
1006 void WebEnginePart::createWalletActions()
1007 {
1008     QAction *a = new QAction(i18nc("Fill the Forms with Data from KWallet", "&Fill forms now"), this);
1009     actionCollection()->addAction("walletFillFormsNow", a);
1010     actionCollection()->setDefaultShortcut(a, QKeySequence("Ctrl+Shift+V"));
1011     connect(a, &QAction::triggered, this, [this]{if(page() && m_wallet){m_wallet->detectAndFillPageForms(page());}});
1012 
1013     a = new QAction(i18n("&Memorize Passwords in This Page Now"), this);
1014     actionCollection()->addAction("walletCacheFormsNow", a);
1015     connect(a, &QAction::triggered, this, [this]{if (page() && m_wallet){m_wallet->savePageDataNow(page());}});
1016 
1017     a = new QAction(i18n("&Customize Fields to Memorize for This Page..."), this);
1018     actionCollection()->addAction("walletCustomizeFields", a);
1019     connect(a, &QAction::triggered, this, [this](){if (m_wallet){m_wallet->customizeFieldsToCache(page(), view());}});
1020 
1021     a = new QAction(i18n("Remove Customized Memorization Settings for This Page"), this);
1022     actionCollection()->addAction("walletRemoveCustomization", a);
1023     connect(a, &QAction::triggered, this, [this](){m_wallet->removeCustomizationForPage(url());});
1024 
1025     KToggleAction *ta = new KToggleAction (i18n("&Allow Password Caching for This Site"), this);
1026     actionCollection()->addAction("walletDisablePasswordCaching", ta);
1027     connect(ta, &QAction::triggered, this, &WebEnginePart::togglePasswordStorableState);
1028 
1029     a = new QAction(i18n("Remove All Memorized Passwords for This Site"), this);
1030     actionCollection()->addAction("walletRemoveCachedData", a);
1031     connect(a, &QAction::triggered, this, &WebEnginePart::slotRemoveCachedPasswords);
1032 
1033     a = new QAction(i18n("&Launch Wallet Manager"), this);
1034     actionCollection()->addAction("walletShowManager", a);
1035     connect(a, &QAction::triggered, this, &WebEnginePart::slotLaunchWalletManager);
1036 
1037     a = new QAction(i18n("&Close Wallet"), this);
1038     actionCollection()->addAction("walletCloseWallet", a);
1039     connect(a, &QAction::triggered, this, &WebEnginePart::resetWallet);
1040 
1041     updateWalletActions();
1042 }
1043 
1044 void WebEnginePart::updateWalletActions()
1045 {
1046     bool enableCaching = m_webView && !WebEngineSettings::self()->isNonPasswordStorableSite(m_webView->url().host());
1047     bool hasCustomForms = m_wallet && m_wallet->hasCustomizedCacheableForms(url());
1048     actionCollection()->action("walletFillFormsNow")->setEnabled(enableCaching && m_wallet && m_walletData.hasCachedData);
1049     actionCollection()->action("walletCacheFormsNow")->setEnabled(enableCaching && m_wallet && (m_walletData.hasAutoFillableForms || hasCustomForms));
1050     actionCollection()->action("walletCustomizeFields")->setEnabled(enableCaching && m_walletData.hasForms);
1051     actionCollection()->action("walletRemoveCustomization")->setEnabled(hasCustomForms);
1052     QAction *a = actionCollection()->action("walletDisablePasswordCaching");
1053     a->setChecked(enableCaching);
1054     a->setEnabled(m_walletData.hasForms);
1055     actionCollection()->action("walletRemoveCachedData")->setEnabled(m_walletData.hasCachedData);
1056     actionCollection()->action("walletCloseWallet")->setEnabled(m_wallet && m_wallet->isOpen());
1057 }
1058 
1059 void WebEnginePart::updateWalletData(WebEnginePart::WalletData::Member which, bool status)
1060 {
1061     switch (which) {
1062         case WalletData::HasForms:
1063             m_walletData.hasForms = status;
1064             break;
1065         case WalletData::HasAutofillableForms:
1066             m_walletData.hasAutoFillableForms = status;
1067             break;
1068         case WalletData::HasCachedData:
1069             m_walletData.hasCachedData = status;
1070             break;
1071     }
1072     updateWalletActions();
1073     updateWalletStatusBarIcon();
1074 }
1075 
1076 void WebEnginePart::updateWalletData(std::initializer_list<bool> data)
1077 {
1078     Q_ASSERT(data.size() > 0 && data.size() < 4);
1079     int size = data.size();
1080     auto it = data.begin();
1081     m_walletData.hasForms = it[0];
1082     if (size > 1) {
1083         m_walletData.hasAutoFillableForms = it[1];
1084     }
1085     if (size > 2) {
1086         m_walletData.hasAutoFillableForms = it[2];
1087     }
1088     updateWalletActions();
1089     updateWalletStatusBarIcon();
1090 }
1091 
1092 void WebEnginePart::setInspectedPart(KParts::ReadOnlyPart* part)
1093 {
1094     WebEnginePart *wpart = qobject_cast<WebEnginePart*>(part);
1095     if (!wpart) {
1096         return;
1097     }
1098     page()->setInspectedPage(wpart->page());
1099     setUrl(page()->url());
1100 }
1101 
1102 void WebEnginePart::reloadAfterUAChange(const QString &)
1103 {
1104     if (!page()) {
1105         return;
1106     }
1107     //NOTE: usually local files won't be affected by this, so don't automatically reload them
1108     if (!url().isLocalFile() && !url().isEmpty() && url().scheme() != "konq") {
1109         m_webView->triggerPageAction(QWebEnginePage::Reload);
1110     }
1111 }
1112 
1113 #if QT_VERSION_MAJOR < 6
1114 KParts::NavigationExtension* WebEnginePart::navigationExtension() const
1115 {
1116     return browserExtension();
1117 }
1118 #endif
1119 
1120 BrowserExtension *WebEnginePart::browserExtension() const
1121 {
1122     return findChild<BrowserExtension *>();
1123 }