File indexing completed on 2024-04-14 04:37:46
0001 /* 0002 SPDX-FileCopyrightText: 2009 Dawit Alemayehu <adawit@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "kwebkitpart_ext.h" 0008 0009 #include "kwebkitpart_debug.h" 0010 #include "kwebkitpart.h" 0011 #include "webview.h" 0012 #include "webpage.h" 0013 #include "settings/webkitsettings.h" 0014 0015 #include <KUriFilter> 0016 #include <KConfigGroup> 0017 #include <KToolInvocation> 0018 #include <KSharedConfig> 0019 #include <KIO/OpenUrlJob> 0020 #include <KIO/JobUiDelegate> 0021 #include <KLocalizedString> 0022 0023 #include <Sonnet/Dialog> 0024 #include <Sonnet/BackgroundChecker> 0025 0026 #include <QAction> 0027 #include <QBuffer> 0028 #include <QClipboard> 0029 #include <QDir> 0030 #include <QApplication> 0031 #include <QInputDialog> 0032 #include <QPrintDialog> 0033 #include <QPrintPreviewDialog> 0034 #include <QTemporaryFile> 0035 #include <QMimeData> 0036 #include <QWebHistory> 0037 #include <QWebElementCollection> 0038 0039 #define QL1S(x) QLatin1String(x) 0040 #define QL1C(x) QLatin1Char(x) 0041 0042 0043 WebKitBrowserExtension::WebKitBrowserExtension(KWebKitPart *parent, const QByteArray& cachedHistoryData) 0044 :KParts::BrowserExtension(parent), 0045 m_part(parent) 0046 { 0047 enableAction("cut", false); 0048 enableAction("copy", false); 0049 enableAction("paste", false); 0050 enableAction("print", true); 0051 0052 if (cachedHistoryData.isEmpty()) { 0053 return; 0054 } 0055 0056 QBuffer buffer; 0057 buffer.setData(cachedHistoryData); 0058 if (!buffer.open(QIODevice::ReadOnly)) { 0059 return; 0060 } 0061 0062 // NOTE: When restoring history, webkit automatically navigates to 0063 // the previous "currentItem". Since we do not want that to happen, 0064 // we set a property on the WebPage object that is used to allow or 0065 // disallow history navigation in WebPage::acceptNavigationRequest. 0066 view()->page()->setProperty("HistoryNavigationLocked", true); 0067 QDataStream s (&buffer); 0068 s >> *(view()->history()); 0069 } 0070 0071 WebKitBrowserExtension::~WebKitBrowserExtension() 0072 { 0073 } 0074 0075 WebView* WebKitBrowserExtension::view() 0076 { 0077 if (!m_view && m_part) { 0078 m_view = qobject_cast<WebView*>(m_part->view()); 0079 } 0080 0081 return m_view; 0082 } 0083 0084 int WebKitBrowserExtension::xOffset() 0085 { 0086 if (view()) 0087 return view()->page()->mainFrame()->scrollPosition().x(); 0088 0089 return KParts::BrowserExtension::xOffset(); 0090 } 0091 0092 int WebKitBrowserExtension::yOffset() 0093 { 0094 if (view()) 0095 return view()->page()->mainFrame()->scrollPosition().y(); 0096 0097 return KParts::BrowserExtension::yOffset(); 0098 } 0099 0100 void WebKitBrowserExtension::saveState(QDataStream &stream) 0101 { 0102 // TODO: Save information such as form data from the current page. 0103 QWebHistory* history = (view() ? view()->history() : nullptr); 0104 const int historyIndex = (history ? history->currentItemIndex() : -1); 0105 const QUrl historyUrl = (history ? QUrl(history->currentItem().url()) : m_part->url()); 0106 0107 stream << historyUrl 0108 << static_cast<qint32>(xOffset()) 0109 << static_cast<qint32>(yOffset()) 0110 << historyIndex 0111 << m_historyData; 0112 } 0113 0114 void WebKitBrowserExtension::restoreState(QDataStream &stream) 0115 { 0116 QUrl u; 0117 QByteArray historyData; 0118 qint32 xOfs = -1, yOfs = -1, historyItemIndex = -1; 0119 stream >> u >> xOfs >> yOfs >> historyItemIndex >> historyData; 0120 0121 QWebHistory* history = (view() ? view()->page()->history() : nullptr); 0122 if (history) { 0123 bool success = false; 0124 if (history->count() == 0) { // Handle restoration: crash recovery, tab close undo, session restore 0125 if (!historyData.isEmpty()) { 0126 historyData = qUncompress(historyData); // uncompress the history data... 0127 QBuffer buffer (&historyData); 0128 if (buffer.open(QIODevice::ReadOnly)) { 0129 QDataStream stream (&buffer); 0130 view()->page()->setProperty("HistoryNavigationLocked", true); 0131 stream >> *history; 0132 QWebHistoryItem currentItem (history->currentItem()); 0133 if (currentItem.isValid()) { 0134 if (currentItem.userData().isNull() && (xOfs != -1 || yOfs != -1)) { 0135 const QPoint scrollPos (xOfs, yOfs); 0136 currentItem.setUserData(scrollPos); 0137 } 0138 // NOTE 1: The following Konqueror specific workaround is necessary 0139 // because Konqueror only preserves information for the last visited 0140 // page. However, we save the entire history content in saveState and 0141 // and hence need to elimiate all but the current item here. 0142 // NOTE 2: This condition only applies when Konqueror is restored from 0143 // abnormal termination ; a crash and/or a session restoration. 0144 if (QCoreApplication::applicationName() == QLatin1String("konqueror")) { 0145 history->clear(); 0146 } 0147 //qCDebug(KWEBKITPART_LOG) << "Restoring URL:" << currentItem.url(); 0148 m_part->setProperty("NoEmitOpenUrlNotification", true); 0149 history->goToItem(currentItem); 0150 } 0151 } 0152 } 0153 success = (history->count() > 0); 0154 } else { // Handle navigation: back and forward button navigation. 0155 //qCDebug(KWEBKITPART_LOG) << "history count:" << history->count() << "request index:" << historyItemIndex; 0156 if (history->count() > historyItemIndex && historyItemIndex > -1) { 0157 QWebHistoryItem item (history->itemAt(historyItemIndex)); 0158 //qCDebug(KWEBKITPART_LOG) << "URL:" << u << "Item URL:" << item.url(); 0159 if (u == item.url()) { 0160 if (item.userData().isNull() && (xOfs != -1 || yOfs != -1)) { 0161 const QPoint scrollPos (xOfs, yOfs); 0162 item.setUserData(scrollPos); 0163 } 0164 m_part->setProperty("NoEmitOpenUrlNotification", true); 0165 history->goToItem(item); 0166 success = true; 0167 } 0168 } 0169 } 0170 0171 if (success) { 0172 return; 0173 } 0174 } 0175 0176 // As a last resort, in case the history restoration logic above fails, 0177 // attempt to open the requested URL directly. 0178 qCDebug(KWEBKITPART_LOG) << "Normal history navgation logic failed! Falling back to opening url directly."; 0179 m_part->openUrl(u); 0180 } 0181 0182 0183 void WebKitBrowserExtension::cut() 0184 { 0185 if (view()) 0186 view()->triggerPageAction(QWebPage::Cut); 0187 } 0188 0189 void WebKitBrowserExtension::copy() 0190 { 0191 if (view()) 0192 view()->triggerPageAction(QWebPage::Copy); 0193 } 0194 0195 void WebKitBrowserExtension::paste() 0196 { 0197 if (view()) 0198 view()->triggerPageAction(QWebPage::Paste); 0199 } 0200 0201 void WebKitBrowserExtension::slotSaveDocument() 0202 { 0203 if (view()) 0204 emit saveUrl(view()->url()); 0205 } 0206 0207 void WebKitBrowserExtension::slotSaveFrame() 0208 { 0209 if (view()) 0210 emit saveUrl(view()->page()->currentFrame()->url()); 0211 } 0212 0213 void WebKitBrowserExtension::print() 0214 { 0215 if (view()) 0216 slotPrintRequested(view()->page()->currentFrame()); 0217 } 0218 0219 void WebKitBrowserExtension::updateEditActions() 0220 { 0221 if (!view()) 0222 return; 0223 0224 enableAction("cut", view()->pageAction(QWebPage::Cut)->isEnabled()); 0225 enableAction("copy", view()->pageAction(QWebPage::Copy)->isEnabled()); 0226 enableAction("paste", view()->pageAction(QWebPage::Paste)->isEnabled()); 0227 } 0228 0229 void WebKitBrowserExtension::updateActions() 0230 { 0231 const QString protocol (m_part->url().scheme()); 0232 const bool isValidDocument = (protocol != QL1S("about") && protocol != QL1S("error")); 0233 enableAction("print", isValidDocument); 0234 } 0235 0236 void WebKitBrowserExtension::searchProvider() 0237 { 0238 if (!view()) 0239 return; 0240 0241 QAction *action = qobject_cast<QAction*>(sender()); 0242 if (!action) 0243 return; 0244 0245 QUrl url = action->data().toUrl(); 0246 0247 if (url.host().isEmpty()) { 0248 KUriFilterData data; 0249 data.setData(action->data().toString()); 0250 if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) 0251 url = data.uri(); 0252 } 0253 0254 if (!url.isValid()) 0255 return; 0256 0257 KParts::BrowserArguments bargs; 0258 bargs.frameName = QL1S("_blank"); 0259 emit openUrlRequest(url, KParts::OpenUrlArguments(), bargs); 0260 } 0261 0262 void WebKitBrowserExtension::reparseConfiguration() 0263 { 0264 // Force the configuration stuff to reparse... 0265 WebKitSettings::self()->init(); 0266 } 0267 0268 void WebKitBrowserExtension::disableScrolling() 0269 { 0270 QWebView* currentView = view(); 0271 QWebPage* page = currentView ? currentView->page() : nullptr; 0272 QWebFrame* frame = page ? page->mainFrame() : nullptr; 0273 0274 if (!frame) 0275 return; 0276 0277 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); 0278 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); 0279 } 0280 0281 void WebKitBrowserExtension::zoomIn() 0282 { 0283 if (view()) 0284 view()->setZoomFactor(view()->zoomFactor() + 0.1); 0285 } 0286 0287 void WebKitBrowserExtension::zoomOut() 0288 { 0289 if (view()) 0290 view()->setZoomFactor(view()->zoomFactor() - 0.1); 0291 } 0292 0293 void WebKitBrowserExtension::zoomNormal() 0294 { 0295 if (view()) { 0296 if (WebKitSettings::self()->zoomToDPI()) 0297 view()->setZoomFactor(view()->logicalDpiY() / 96.0f); 0298 else 0299 view()->setZoomFactor(1); 0300 } 0301 } 0302 0303 void WebKitBrowserExtension::toogleZoomTextOnly() 0304 { 0305 if (!view()) 0306 return; 0307 0308 KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings"); 0309 bool zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false ); 0310 cgHtml.writeEntry("ZoomTextOnly", !zoomTextOnly); 0311 cgHtml.sync(); 0312 0313 view()->settings()->setAttribute(QWebSettings::ZoomTextOnly, !zoomTextOnly); 0314 } 0315 0316 void WebKitBrowserExtension::toogleZoomToDPI() 0317 { 0318 if (!view()) 0319 return; 0320 0321 bool zoomToDPI = !WebKitSettings::self()->zoomToDPI(); 0322 WebKitSettings::self()->setZoomToDPI(zoomToDPI); 0323 0324 if (zoomToDPI) 0325 view()->setZoomFactor(view()->zoomFactor() * view()->logicalDpiY() / 96.0f); 0326 else 0327 view()->setZoomFactor(view()->zoomFactor() * 96.0f / view()->logicalDpiY()); 0328 0329 // Recompute default font-sizes since they are only DPI dependent when zoomToDPI is false. 0330 WebKitSettings::self()->computeFontSizes(view()->logicalDpiY()); 0331 } 0332 0333 void WebKitBrowserExtension::slotSelectAll() 0334 { 0335 if (view()) 0336 view()->triggerPageAction(QWebPage::SelectAll); 0337 } 0338 0339 void WebKitBrowserExtension::slotFrameInWindow() 0340 { 0341 if (!view()) 0342 return; 0343 0344 KParts::BrowserArguments bargs; 0345 bargs.setForcesNewWindow(true); 0346 0347 KParts::OpenUrlArguments uargs; 0348 uargs.setActionRequestedByUser(true); 0349 0350 QUrl url (view()->page()->currentFrame()->baseUrl()); 0351 url = url.resolved(view()->page()->currentFrame()->url()); 0352 0353 emit createNewWindow(url, uargs, bargs); 0354 } 0355 0356 void WebKitBrowserExtension::slotFrameInTab() 0357 { 0358 if (!view()) 0359 return; 0360 0361 KParts::OpenUrlArguments uargs; 0362 uargs.setActionRequestedByUser(true); 0363 0364 KParts::BrowserArguments bargs; 0365 bargs.setNewTab(true); 0366 0367 QUrl url (view()->page()->currentFrame()->baseUrl()); 0368 url = url.resolved(view()->page()->currentFrame()->url()); 0369 0370 emit createNewWindow(url, uargs, bargs); 0371 } 0372 0373 void WebKitBrowserExtension::slotFrameInTop() 0374 { 0375 if (!view()) 0376 return; 0377 0378 KParts::OpenUrlArguments uargs; 0379 uargs.setActionRequestedByUser(true); 0380 0381 KParts::BrowserArguments bargs; 0382 bargs.frameName = QL1S("_top"); 0383 0384 QUrl url (view()->page()->currentFrame()->baseUrl()); 0385 url = url.resolved(view()->page()->currentFrame()->url()); 0386 0387 emit openUrlRequest(url, uargs, bargs); 0388 } 0389 0390 void WebKitBrowserExtension::slotReloadFrame() 0391 { 0392 if (view()) 0393 view()->page()->currentFrame()->load(view()->page()->currentFrame()->url()); 0394 } 0395 0396 static QString iframeUrl(QWebFrame* frame) 0397 { 0398 return ((frame && frame->baseUrl().isValid()) ? frame->baseUrl() : frame->url()).toString(); 0399 } 0400 0401 void WebKitBrowserExtension::slotBlockIFrame() 0402 { 0403 if (!view()) 0404 return; 0405 0406 bool ok = false; 0407 const QString urlStr = iframeUrl(view()->contextMenuResult().frame()); 0408 const QString url = QInputDialog::getText(view(), 0409 i18n("Add URL to Filter"), 0410 i18n("Enter the URL:"), 0411 QLineEdit::Normal, 0412 urlStr, &ok); 0413 if (ok && !url.isEmpty()) { 0414 WebKitSettings::self()->addAdFilter(url); 0415 reparseConfiguration(); 0416 } 0417 } 0418 0419 void WebKitBrowserExtension::slotSaveImageAs() 0420 { 0421 if (view()) 0422 view()->triggerPageAction(QWebPage::DownloadImageToDisk); 0423 } 0424 0425 void WebKitBrowserExtension::slotSendImage() 0426 { 0427 if (!view()) 0428 return; 0429 0430 QStringList urls; 0431 urls.append(view()->contextMenuResult().imageUrl().path()); 0432 const QString subject = view()->contextMenuResult().imageUrl().path(); 0433 KToolInvocation::invokeMailer(QString(), QString(), QString(), subject, 0434 QString(), //body 0435 QString(), 0436 urls); // attachments 0437 } 0438 0439 void WebKitBrowserExtension::slotCopyImageURL() 0440 { 0441 if (!view()) 0442 return; 0443 0444 QUrl safeURL(view()->contextMenuResult().imageUrl()); 0445 safeURL.setPassword(QString()); 0446 // Set it in both the mouse selection and in the clipboard 0447 QMimeData* mimeData = new QMimeData; 0448 //TODO: Porting: test 0449 QList<QUrl> safeURLList; 0450 safeURLList.append(safeURL); 0451 mimeData->setUrls(safeURLList); 0452 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); 0453 0454 mimeData = new QMimeData; 0455 mimeData->setUrls(safeURLList); 0456 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); 0457 } 0458 0459 0460 void WebKitBrowserExtension::slotCopyImage() 0461 { 0462 if (!view()) 0463 return; 0464 0465 QUrl safeURL(view()->contextMenuResult().imageUrl()); 0466 safeURL.setPassword(QString()); 0467 0468 // Set it in both the mouse selection and in the clipboard 0469 QMimeData* mimeData = new QMimeData; 0470 mimeData->setImageData(view()->contextMenuResult().pixmap()); 0471 //TODO: Porting: test 0472 QList<QUrl> safeURLList; 0473 safeURLList.append(safeURL); 0474 mimeData->setUrls(safeURLList); 0475 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); 0476 0477 mimeData = new QMimeData; 0478 mimeData->setImageData(view()->contextMenuResult().pixmap()); 0479 mimeData->setUrls(safeURLList); 0480 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); 0481 } 0482 0483 void WebKitBrowserExtension::slotViewImage() 0484 { 0485 if (view()) 0486 emit createNewWindow(view()->contextMenuResult().imageUrl()); 0487 } 0488 0489 void WebKitBrowserExtension::slotBlockImage() 0490 { 0491 if (!view()) 0492 return; 0493 0494 bool ok = false; 0495 const QString url = QInputDialog::getText(view(), 0496 i18n("Add URL to Filter"), 0497 i18n("Enter the URL:"), 0498 QLineEdit::Normal, 0499 view()->contextMenuResult().imageUrl().toString(), 0500 &ok); 0501 if (ok && !url.isEmpty()) { 0502 WebKitSettings::self()->addAdFilter(url); 0503 reparseConfiguration(); 0504 } 0505 } 0506 0507 void WebKitBrowserExtension::slotBlockHost() 0508 { 0509 if (!view()) 0510 return; 0511 0512 QUrl url (view()->contextMenuResult().imageUrl()); 0513 url.setPath(QL1S("/*")); 0514 WebKitSettings::self()->addAdFilter(url.toString(QUrl::RemoveUserInfo | QUrl::RemovePort)); 0515 reparseConfiguration(); 0516 } 0517 0518 void WebKitBrowserExtension::slotCopyLinkURL() 0519 { 0520 if (view()) 0521 view()->triggerPageAction(QWebPage::CopyLinkToClipboard); 0522 } 0523 0524 void WebKitBrowserExtension::slotCopyLinkText() 0525 { 0526 if (view()) { 0527 QMimeData* data = new QMimeData; 0528 data->setText(view()->contextMenuResult().linkText()); 0529 QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); 0530 } 0531 } 0532 0533 void WebKitBrowserExtension::slotCopyEmailAddress() 0534 { 0535 if (view()) { 0536 QMimeData* data = new QMimeData; 0537 const QUrl url (view()->contextMenuResult().linkUrl()); 0538 data->setText(url.path()); 0539 QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); 0540 } 0541 } 0542 0543 void WebKitBrowserExtension::slotSaveLinkAs() 0544 { 0545 if (view()) 0546 view()->triggerPageAction(QWebPage::DownloadLinkToDisk); 0547 } 0548 0549 void WebKitBrowserExtension::slotViewDocumentSource() 0550 { 0551 if (!view()) 0552 return; 0553 0554 const QUrl pageUrl (view()->url()); 0555 if (pageUrl.isLocalFile()) { 0556 auto* job = new KIO::OpenUrlJob(pageUrl, QL1S("text/plain")); 0557 job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, view())); 0558 job->start(); 0559 } else { 0560 QTemporaryFile tempFile(QDir::tempPath() + 0561 QLatin1Char('/') + 0562 QCoreApplication::applicationName() + 0563 QLatin1String("XXXXXX.html")); 0564 tempFile.setAutoRemove(false); 0565 if (tempFile.open()) { 0566 tempFile.write(view()->page()->mainFrame()->toHtml().toUtf8()); 0567 tempFile.close(); 0568 auto* job = new KIO::OpenUrlJob(QUrl::fromLocalFile(tempFile.fileName()), QL1S("text/plain")); 0569 job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, view())); 0570 job->setDeleteTemporaryFile(true); 0571 job->start(); 0572 } 0573 } 0574 } 0575 0576 void WebKitBrowserExtension::slotViewFrameSource() 0577 { 0578 if (!view()) 0579 return; 0580 0581 const QUrl frameUrl(view()->page()->currentFrame()->url()); 0582 if (frameUrl.isLocalFile()) { 0583 auto* job = new KIO::OpenUrlJob(frameUrl, QL1S("text/plain")); 0584 job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, view())); 0585 job->start(); 0586 } else { 0587 QTemporaryFile tempFile(QDir::tempPath() + 0588 QLatin1Char('/') + 0589 QCoreApplication::applicationName() + 0590 QLatin1String("XXXXXX.html")); 0591 tempFile.setAutoRemove(false); 0592 if (tempFile.open()) { 0593 tempFile.write(view()->page()->currentFrame()->toHtml().toUtf8()); 0594 tempFile.close(); 0595 auto* job = new KIO::OpenUrlJob(QUrl::fromLocalFile(tempFile.fileName()), QL1S("text/plain")); 0596 job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, view())); 0597 job->setDeleteTemporaryFile(true); 0598 job->start(); 0599 } 0600 } 0601 } 0602 0603 static bool isMultimediaElement(const QWebElement& element) 0604 { 0605 if (element.tagName().compare(QL1S("video"), Qt::CaseInsensitive) == 0) 0606 return true; 0607 0608 if (element.tagName().compare(QL1S("audio"), Qt::CaseInsensitive) == 0) 0609 return true; 0610 0611 return false; 0612 } 0613 0614 void WebKitBrowserExtension::slotLoopMedia() 0615 { 0616 if (!view()) 0617 return; 0618 0619 QWebElement element (view()->contextMenuResult().element()); 0620 if (!isMultimediaElement(element)) 0621 return; 0622 0623 element.evaluateJavaScript(QL1S("this.loop = !this.loop;")); 0624 } 0625 0626 void WebKitBrowserExtension::slotMuteMedia() 0627 { 0628 if (!view()) 0629 return; 0630 0631 QWebElement element (view()->contextMenuResult().element()); 0632 if (!isMultimediaElement(element)) 0633 return; 0634 0635 element.evaluateJavaScript(QL1S("this.muted = !this.muted;")); 0636 } 0637 0638 void WebKitBrowserExtension::slotPlayMedia() 0639 { 0640 if (!view()) 0641 return; 0642 0643 QWebElement element (view()->contextMenuResult().element()); 0644 if (!isMultimediaElement(element)) 0645 return; 0646 0647 element.evaluateJavaScript(QL1S("this.paused ? this.play() : this.pause();")); 0648 } 0649 0650 void WebKitBrowserExtension::slotShowMediaControls() 0651 { 0652 if (!view()) 0653 return; 0654 0655 QWebElement element (view()->contextMenuResult().element()); 0656 if (!isMultimediaElement(element)) 0657 return; 0658 0659 element.evaluateJavaScript(QL1S("this.controls = !this.controls;")); 0660 } 0661 0662 static QUrl mediaUrlFrom(QWebElement& element) 0663 { 0664 QWebFrame* frame = element.webFrame(); 0665 QString src = frame ? element.attribute(QL1S("src")) : QString(); 0666 if (src.isEmpty()) 0667 src = frame ? element.evaluateJavaScript(QL1S("this.src")).toString() : QString(); 0668 0669 if (src.isEmpty()) 0670 return QUrl(); 0671 0672 return QUrl(frame->baseUrl().resolved(QUrl::fromEncoded(QUrl::toPercentEncoding(src), QUrl::StrictMode))); 0673 } 0674 0675 void WebKitBrowserExtension::slotSaveMedia() 0676 { 0677 if (!view()) 0678 return; 0679 0680 QWebElement element (view()->contextMenuResult().element()); 0681 if (!isMultimediaElement(element)) 0682 return; 0683 0684 emit saveUrl(mediaUrlFrom(element)); 0685 } 0686 0687 void WebKitBrowserExtension::slotCopyMedia() 0688 { 0689 if (!view()) 0690 return; 0691 0692 QWebElement element (view()->contextMenuResult().element()); 0693 if (!isMultimediaElement(element)) 0694 return; 0695 0696 QUrl safeURL(mediaUrlFrom(element)); 0697 if (!safeURL.isValid()) 0698 return; 0699 0700 safeURL.setPassword(QString()); 0701 // Set it in both the mouse selection and in the clipboard 0702 QMimeData* mimeData = new QMimeData; 0703 //TODO: Porting: test 0704 QList<QUrl> safeURLList; 0705 safeURLList.append(safeURL); 0706 mimeData->setUrls(safeURLList); 0707 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); 0708 0709 mimeData = new QMimeData; 0710 mimeData->setUrls(safeURLList); 0711 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); 0712 } 0713 0714 void WebKitBrowserExtension::slotTextDirectionChanged() 0715 { 0716 QAction* action = qobject_cast<QAction*>(sender()); 0717 if (action) { 0718 bool ok = false; 0719 const int value = action->data().toInt(&ok); 0720 if (ok) { 0721 view()->triggerPageAction(static_cast<QWebPage::WebAction>(value)); 0722 } 0723 } 0724 } 0725 0726 static QVariant execJScript(WebView* view, const QString& script) 0727 { 0728 QWebElement element (view->contextMenuResult().element()); 0729 if (element.isNull()) 0730 return QVariant(); 0731 return element.evaluateJavaScript(script); 0732 } 0733 0734 void WebKitBrowserExtension::slotCheckSpelling() 0735 { 0736 const QString text (execJScript(view(), QL1S("this.value")).toString()); 0737 0738 if ( text.isEmpty() ) { 0739 return; 0740 } 0741 0742 m_spellTextSelectionStart = 0; 0743 m_spellTextSelectionEnd = 0; 0744 0745 Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; 0746 Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); 0747 backgroundSpellCheck->setParent(spellDialog); 0748 spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); 0749 spellDialog->showSpellCheckCompletionMessage(true); 0750 connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); 0751 connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); 0752 spellDialog->setBuffer(text); 0753 spellDialog->show(); 0754 } 0755 0756 void WebKitBrowserExtension::slotSpellCheckSelection() 0757 { 0758 QString text (execJScript(view(), QL1S("this.value")).toString()); 0759 0760 if ( text.isEmpty() ) { 0761 return; 0762 } 0763 0764 m_spellTextSelectionStart = qMax(0, execJScript(view(), QL1S("this.selectionStart")).toInt()); 0765 m_spellTextSelectionEnd = qMax(0, execJScript(view(), QL1S("this.selectionEnd")).toInt()); 0766 // qCDebug(KWEBKITPART_LOG) << "selection start:" << m_spellTextSelectionStart << "end:" << m_spellTextSelectionEnd; 0767 0768 Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; 0769 Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); 0770 backgroundSpellCheck->setParent(spellDialog); 0771 spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); 0772 spellDialog->showSpellCheckCompletionMessage(true); 0773 connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); 0774 connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); 0775 connect(spellDialog, SIGNAL(done(QString)), this, SLOT(slotSpellCheckDone(QString))); 0776 spellDialog->setBuffer(text.mid(m_spellTextSelectionStart, (m_spellTextSelectionEnd - m_spellTextSelectionStart))); 0777 spellDialog->show(); 0778 } 0779 0780 void WebKitBrowserExtension::spellCheckerCorrected(const QString& original, int pos, const QString& replacement) 0781 { 0782 // Adjust the selection end... 0783 if (m_spellTextSelectionEnd > 0) { 0784 m_spellTextSelectionEnd += qMax (0, (replacement.length() - original.length())); 0785 } 0786 0787 const int index = pos + m_spellTextSelectionStart; 0788 QString script(QL1S("this.value=this.value.substring(0,")); 0789 script += QString::number(index); 0790 script += QL1S(") + \""); 0791 script += replacement; 0792 script += QL1S("\" + this.value.substring("); 0793 script += QString::number(index + original.length()); 0794 script += QL1S(")"); 0795 0796 //qCDebug(KWEBKITPART_LOG) << "**** script:" << script; 0797 execJScript(view(), script); 0798 } 0799 0800 void WebKitBrowserExtension::spellCheckerMisspelling(const QString& text, int pos) 0801 { 0802 // qCDebug(KWEBKITPART_LOG) << text << pos; 0803 QString selectionScript (QL1S("this.setSelectionRange(")); 0804 selectionScript += QString::number(pos + m_spellTextSelectionStart); 0805 selectionScript += QL1C(','); 0806 selectionScript += QString::number(pos + text.length() + m_spellTextSelectionStart); 0807 selectionScript += QL1C(')'); 0808 execJScript(view(), selectionScript); 0809 } 0810 0811 void WebKitBrowserExtension::slotSpellCheckDone(const QString&) 0812 { 0813 // Restore the text selection if one was present before we started the 0814 // spell check. 0815 if (m_spellTextSelectionStart > 0 || m_spellTextSelectionEnd > 0) { 0816 QString script (QL1S("; this.setSelectionRange(")); 0817 script += QString::number(m_spellTextSelectionStart); 0818 script += QL1C(','); 0819 script += QString::number(m_spellTextSelectionEnd); 0820 script += QL1C(')'); 0821 execJScript(view(), script); 0822 } 0823 } 0824 0825 0826 void WebKitBrowserExtension::saveHistory() 0827 { 0828 QWebHistory* history = (view() ? view()->history() : nullptr); 0829 0830 if (history && history->count() > 0) { 0831 //qCDebug(KWEBKITPART_LOG) << "Current history: index=" << history->currentItemIndex() << "url=" << history->currentItem().url(); 0832 QByteArray histData; 0833 QBuffer buff (&histData); 0834 m_historyData.clear(); 0835 if (buff.open(QIODevice::WriteOnly)) { 0836 QDataStream stream (&buff); 0837 stream << *history; 0838 m_historyData = qCompress(histData, 9); 0839 } 0840 QWidget* mainWidget = m_part ? m_part->widget() : nullptr; 0841 QWidget* frameWidget = mainWidget ? mainWidget->parentWidget() : nullptr; 0842 if (frameWidget) { 0843 emit saveHistory(frameWidget, m_historyData); 0844 // qCDebug(KWEBKITPART_LOG) << "# of items:" << history->count() << "current item:" << history->currentItemIndex() << "url:" << history->currentItem().url(); 0845 } 0846 } else { 0847 Q_ASSERT(false); // should never happen!!! 0848 } 0849 } 0850 0851 void WebKitBrowserExtension::slotPrintRequested(QWebFrame* frame) 0852 { 0853 if (!frame) 0854 return; 0855 0856 // Make it non-modal, in case a redirection deletes the part 0857 QPointer<QPrintDialog> dlg (new QPrintDialog(view())); 0858 if (dlg->exec() == QPrintDialog::Accepted) { 0859 frame->print(dlg->printer()); 0860 } 0861 delete dlg; 0862 } 0863 0864 void WebKitBrowserExtension::slotPrintPreview() 0865 { 0866 // Make it non-modal, in case a redirection deletes the part 0867 QPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(view())); 0868 connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), 0869 view()->page()->currentFrame(), SLOT(print(QPrinter*))); 0870 dlg->exec(); 0871 delete dlg; 0872 } 0873 0874 void WebKitBrowserExtension::slotOpenSelection() 0875 { 0876 QAction *action = qobject_cast<QAction*>(sender()); 0877 if (action) { 0878 KParts::BrowserArguments browserArgs; 0879 browserArgs.frameName = "_blank"; 0880 emit openUrlRequest(QUrl(action->data().toUrl()), KParts::OpenUrlArguments(), browserArgs); 0881 } 0882 } 0883 0884 void WebKitBrowserExtension::slotLinkInTop() 0885 { 0886 if (!view()) 0887 return; 0888 0889 KParts::OpenUrlArguments uargs; 0890 uargs.setActionRequestedByUser(true); 0891 0892 KParts::BrowserArguments bargs; 0893 bargs.frameName = QL1S("_top"); 0894 0895 const QUrl url (view()->contextMenuResult().linkUrl()); 0896 0897 emit openUrlRequest(url, uargs, bargs); 0898 } 0899 0900 //// 0901 0902 KWebKitTextExtension::KWebKitTextExtension(KWebKitPart* part) 0903 : KParts::TextExtension(part) 0904 { 0905 connect(part->view(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); 0906 } 0907 0908 KWebKitPart* KWebKitTextExtension::part() const 0909 { 0910 return static_cast<KWebKitPart*>(parent()); 0911 } 0912 0913 bool KWebKitTextExtension::hasSelection() const 0914 { 0915 return part()->view()->hasSelection(); 0916 } 0917 0918 QString KWebKitTextExtension::selectedText(Format format) const 0919 { 0920 switch(format) { 0921 case PlainText: 0922 return part()->view()->selectedText(); 0923 case HTML: 0924 return part()->view()->selectedHtml(); 0925 } 0926 return QString(); 0927 } 0928 0929 QString KWebKitTextExtension::completeText(Format format) const 0930 { 0931 switch(format) { 0932 case PlainText: 0933 return part()->view()->page()->currentFrame()->toPlainText(); 0934 case HTML: 0935 return part()->view()->page()->currentFrame()->toHtml(); 0936 } 0937 return QString(); 0938 } 0939 0940 //// 0941 0942 KWebKitHtmlExtension::KWebKitHtmlExtension(KWebKitPart* part) 0943 : KParts::HtmlExtension(part) 0944 { 0945 } 0946 0947 0948 QUrl KWebKitHtmlExtension::baseUrl() const 0949 { 0950 return part()->view()->page()->mainFrame()->baseUrl(); 0951 } 0952 0953 bool KWebKitHtmlExtension::hasSelection() const 0954 { 0955 return part()->view()->hasSelection(); 0956 } 0957 0958 KParts::SelectorInterface::QueryMethods KWebKitHtmlExtension::supportedQueryMethods() const 0959 { 0960 return (KParts::SelectorInterface::EntireContent 0961 | KParts::SelectorInterface::SelectedContent); 0962 } 0963 0964 static KParts::SelectorInterface::Element convertWebElement(const QWebElement& webElem) 0965 { 0966 KParts::SelectorInterface::Element element; 0967 element.setTagName(webElem.tagName()); 0968 Q_FOREACH(const QString &attr, webElem.attributeNames()) { 0969 element.setAttribute(attr, webElem.attribute(attr)); 0970 } 0971 return element; 0972 } 0973 0974 0975 static QString queryOne(const QString& query) 0976 { 0977 QString jsQuery = QL1S("(function(query) { var element; var selectedElement = window.getSelection().getRangeAt(0).cloneContents().querySelector(\""); 0978 jsQuery += query; 0979 jsQuery += QL1S("\"); if (selectedElement && selectedElement.length > 0) { element = new Object; " 0980 "element.tagName = String(selectedElements[0].tagName); element.href = String(selectedElements[0].href); } " 0981 "return element; }())"); 0982 return jsQuery; 0983 } 0984 0985 static QString queryAll(const QString& query) 0986 { 0987 QString jsQuery = QL1S("(function(query) { var elements = []; var selectedElements = window.getSelection().getRangeAt(0).cloneContents().querySelectorAll(\""); 0988 jsQuery += query; 0989 jsQuery += QL1S("\"); var numSelectedElements = (selectedElements ? selectedElements.length : 0);" 0990 "for (var i = 0; i < numSelectedElements; ++i) { var element = new Object; " 0991 "element.tagName = String(selectedElements[i].tagName); element.href = String(selectedElements[i].href);" 0992 "elements.push(element); } return elements; } ())"); 0993 return jsQuery; 0994 } 0995 0996 static KParts::SelectorInterface::Element convertSelectionElement(const QVariant& variant) 0997 { 0998 KParts::SelectorInterface::Element element; 0999 if (!variant.isNull() && variant.type() == QVariant::Map) { 1000 const QVariantMap elementMap (variant.toMap()); 1001 element.setTagName(elementMap.value(QL1S("tagName")).toString()); 1002 element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); 1003 } 1004 return element; 1005 } 1006 1007 static QList<KParts::SelectorInterface::Element> convertSelectionElements(const QVariant& variant) 1008 { 1009 QList<KParts::SelectorInterface::Element> elements; 1010 const QVariantList resultList (variant.toList()); 1011 Q_FOREACH(const QVariant& result, resultList) { 1012 const QVariantMap elementMap = result.toMap(); 1013 KParts::SelectorInterface::Element element; 1014 element.setTagName(elementMap.value(QL1S("tagName")).toString()); 1015 element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); 1016 elements.append(element); 1017 } 1018 return elements; 1019 } 1020 1021 KParts::SelectorInterface::Element KWebKitHtmlExtension::querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const 1022 { 1023 KParts::SelectorInterface::Element element; 1024 1025 // If the specified method is None, return an empty list... 1026 if (method == KParts::SelectorInterface::None) 1027 return element; 1028 1029 // If the specified method is not supported, return an empty list... 1030 if (!(supportedQueryMethods() & method)) 1031 return element; 1032 1033 switch (method) { 1034 case KParts::SelectorInterface::EntireContent: { 1035 const QWebFrame* webFrame = part()->view()->page()->mainFrame(); 1036 element = convertWebElement(webFrame->findFirstElement(query)); 1037 break; 1038 } 1039 case KParts::SelectorInterface::SelectedContent: { 1040 QWebFrame* webFrame = part()->view()->page()->mainFrame(); 1041 element = convertSelectionElement(webFrame->evaluateJavaScript(queryOne(query))); 1042 break; 1043 } 1044 default: 1045 break; 1046 } 1047 1048 return element; 1049 } 1050 1051 QList<KParts::SelectorInterface::Element> KWebKitHtmlExtension::querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const 1052 { 1053 QList<KParts::SelectorInterface::Element> elements; 1054 1055 // If the specified method is None, return an empty list... 1056 if (method == KParts::SelectorInterface::None) 1057 return elements; 1058 1059 // If the specified method is not supported, return an empty list... 1060 if (!(supportedQueryMethods() & method)) 1061 return elements; 1062 1063 switch (method) { 1064 case KParts::SelectorInterface::EntireContent: { 1065 const QWebFrame* webFrame = part()->view()->page()->mainFrame(); 1066 const QWebElementCollection collection = webFrame->findAllElements(query); 1067 elements.reserve(collection.count()); 1068 Q_FOREACH(const QWebElement& element, collection) 1069 elements.append(convertWebElement(element)); 1070 break; 1071 } 1072 case KParts::SelectorInterface::SelectedContent: { 1073 QWebFrame* webFrame = part()->view()->page()->mainFrame(); 1074 elements = convertSelectionElements(webFrame->evaluateJavaScript(queryAll(query))); 1075 break; 1076 } 1077 default: 1078 break; 1079 } 1080 return elements; 1081 } 1082 1083 QVariant KWebKitHtmlExtension::htmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type) const 1084 { 1085 QWebView* view = part() ? part()->view() : nullptr; 1086 QWebPage* page = view ? view->page() : nullptr; 1087 QWebSettings* settings = page ? page->settings() : nullptr; 1088 1089 if (settings) { 1090 switch (type) { 1091 case KParts::HtmlSettingsInterface::AutoLoadImages: 1092 return settings->testAttribute(QWebSettings::AutoLoadImages); 1093 case KParts::HtmlSettingsInterface::JavaEnabled: 1094 return settings->testAttribute(QWebSettings::JavaEnabled); 1095 case KParts::HtmlSettingsInterface::JavascriptEnabled: 1096 return settings->testAttribute(QWebSettings::JavascriptEnabled); 1097 case KParts::HtmlSettingsInterface::PluginsEnabled: 1098 return settings->testAttribute(QWebSettings::PluginsEnabled); 1099 case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: 1100 return settings->testAttribute(QWebSettings::DnsPrefetchEnabled); 1101 case KParts::HtmlSettingsInterface::MetaRefreshEnabled: 1102 return view->pageAction(QWebPage::StopScheduledPageRefresh)->isEnabled(); 1103 case KParts::HtmlSettingsInterface::LocalStorageEnabled: 1104 return settings->testAttribute(QWebSettings::LocalStorageEnabled); 1105 case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: 1106 return settings->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled); 1107 case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: 1108 return settings->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); 1109 case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: 1110 return settings->testAttribute(QWebSettings::PrivateBrowsingEnabled); 1111 case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: 1112 return settings->userStyleSheetUrl(); 1113 default: 1114 break; 1115 } 1116 } 1117 1118 return QVariant(); 1119 } 1120 1121 bool KWebKitHtmlExtension::setHtmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type, const QVariant& value) 1122 { 1123 QWebView* view = part() ? part()->view() : nullptr; 1124 QWebPage* page = view ? view->page() : nullptr; 1125 QWebSettings* settings = page ? page->settings() : nullptr; 1126 1127 if (settings) { 1128 switch (type) { 1129 case KParts::HtmlSettingsInterface::AutoLoadImages: 1130 settings->setAttribute(QWebSettings::AutoLoadImages, value.toBool()); 1131 return true; 1132 case KParts::HtmlSettingsInterface::JavaEnabled: 1133 settings->setAttribute(QWebSettings::JavaEnabled, value.toBool()); 1134 return true; 1135 case KParts::HtmlSettingsInterface::JavascriptEnabled: 1136 settings->setAttribute(QWebSettings::JavascriptEnabled, value.toBool()); 1137 return true; 1138 case KParts::HtmlSettingsInterface::PluginsEnabled: 1139 settings->setAttribute(QWebSettings::PluginsEnabled, value.toBool()); 1140 return true; 1141 case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: 1142 settings->setAttribute(QWebSettings::DnsPrefetchEnabled, value.toBool()); 1143 return true; 1144 case KParts::HtmlSettingsInterface::MetaRefreshEnabled: 1145 view->triggerPageAction(QWebPage::StopScheduledPageRefresh); 1146 return true; 1147 case KParts::HtmlSettingsInterface::LocalStorageEnabled: 1148 settings->setAttribute(QWebSettings::LocalStorageEnabled, value.toBool()); 1149 return true; 1150 case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: 1151 settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, value.toBool()); 1152 return true; 1153 case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: 1154 settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, value.toBool()); 1155 return true; 1156 case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: 1157 settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, value.toBool()); 1158 return true; 1159 case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: 1160 //qCDebug(KWEBKITPART_LOG) << "Setting user style sheet for" << page << "to" << value.toUrl(); 1161 settings->setUserStyleSheetUrl(value.toUrl()); 1162 return true; 1163 default: 1164 break; 1165 } 1166 } 1167 1168 return false; 1169 } 1170 1171 KWebKitPart* KWebKitHtmlExtension::part() const 1172 { 1173 return static_cast<KWebKitPart*>(parent()); 1174 } 1175 1176 KWebKitScriptableExtension::KWebKitScriptableExtension(KWebKitPart* part) 1177 : ScriptableExtension(part) 1178 { 1179 } 1180 1181 QVariant KWebKitScriptableExtension::rootObject() 1182 { 1183 return QVariant::fromValue(KParts::ScriptableExtension::Object(this, reinterpret_cast<quint64>(this))); 1184 } 1185 1186 bool KWebKitScriptableExtension::setException (KParts::ScriptableExtension* callerPrincipal, const QString& message) 1187 { 1188 return KParts::ScriptableExtension::setException (callerPrincipal, message); 1189 } 1190 1191 QVariant KWebKitScriptableExtension::get (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName) 1192 { 1193 //qCDebug(KWEBKITPART_LOG) << "caller:" << callerPrincipal << "id:" << objId << "propName:" << propName; 1194 return callerPrincipal->get (nullptr, objId, propName); 1195 } 1196 1197 bool KWebKitScriptableExtension::put (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value) 1198 { 1199 return KParts::ScriptableExtension::put (callerPrincipal, objId, propName, value); 1200 } 1201 1202 static QVariant exception(const char* msg) 1203 { 1204 qCWarning(KWEBKITPART_LOG) << msg; 1205 return QVariant::fromValue(KParts::ScriptableExtension::Exception(QString::fromLatin1(msg))); 1206 } 1207 1208 QVariant KWebKitScriptableExtension::evaluateScript (KParts::ScriptableExtension* callerPrincipal, 1209 quint64 contextObjectId, 1210 const QString& code, 1211 KParts::ScriptableExtension::ScriptLanguage lang) 1212 { 1213 Q_UNUSED(contextObjectId); 1214 //qCDebug(KWEBKITPART_LOG) << "principal:" << callerPrincipal << "id:" << contextObjectId << "language:" << lang << "code:" << code; 1215 1216 if (lang != ECMAScript) 1217 return exception("unsupported language"); 1218 1219 1220 KParts::ReadOnlyPart* part = callerPrincipal ? qobject_cast<KParts::ReadOnlyPart*>(callerPrincipal->parent()) : nullptr; 1221 QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : nullptr; 1222 if (!frame) 1223 return exception("failed to resolve principal"); 1224 1225 QVariant result (frame->evaluateJavaScript(code)); 1226 1227 if (result.type() == QVariant::Map) { 1228 const QVariantMap map (result.toMap()); 1229 for (QVariantMap::const_iterator it = map.constBegin(), itEnd = map.constEnd(); it != itEnd; ++it) { 1230 callerPrincipal->put(callerPrincipal, 0, it.key(), it.value()); 1231 } 1232 } else { 1233 const QString propName(code.contains(QLatin1String("__nsplugin")) ? QLatin1String("__nsplugin") : QString()); 1234 callerPrincipal->put(callerPrincipal, 0, propName, result.toString()); 1235 } 1236 1237 return QVariant::fromValue(ScriptableExtension::Null()); 1238 } 1239 1240 bool KWebKitScriptableExtension::isScriptLanguageSupported (KParts::ScriptableExtension::ScriptLanguage lang) const 1241 { 1242 return (lang == KParts::ScriptableExtension::ECMAScript); 1243 } 1244 1245 QVariant KWebKitScriptableExtension::encloserForKid (KParts::ScriptableExtension* kid) 1246 { 1247 KParts::ReadOnlyPart* part = kid ? qobject_cast<KParts::ReadOnlyPart*>(kid->parent()) : nullptr; 1248 QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : nullptr; 1249 if (frame) { 1250 return QVariant::fromValue(KParts::ScriptableExtension::Object(kid, reinterpret_cast<quint64>(kid))); 1251 } 1252 1253 return QVariant::fromValue(ScriptableExtension::Null()); 1254 } 1255 1256 KWebKitPart* KWebKitScriptableExtension::part() 1257 { 1258 return qobject_cast<KWebKitPart*>(parent()); 1259 }