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 }