diff options
Diffstat (limited to 'src/webenginewidgets/api/qwebenginepage.cpp')
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 265 |
1 files changed, 216 insertions, 49 deletions
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 745ce03fc..45519bfd0 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -41,12 +41,16 @@ #include "qwebenginepage_p.h" #include "authentication_dialog_controller.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "certificate_error_controller.h" #include "color_chooser_controller.h" #include "favicon_manager.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" +#if QT_CONFIG(webengine_printing_and_pdf) +#include "printing/pdfium_document_wrapper_qt.h" +#endif +#include "qwebenginecertificateerror.h" #include "qwebenginefullscreenrequest.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" @@ -67,18 +71,28 @@ #include <QApplication> #include <QAuthenticator> #include <QClipboard> +#if QT_CONFIG(colordialog) #include <QColorDialog> +#endif #include <QContextMenuEvent> +#if QT_CONFIG(filedialog) #include <QFileDialog> +#endif #include <QKeyEvent> #include <QIcon> +#if QT_CONFIG(inputdialog) #include <QInputDialog> +#endif #include <QLayout> #include <QLoggingCategory> +#if QT_CONFIG(menu) #include <QMenu> +#endif +#if QT_CONFIG(messagebox) #include <QMessageBox> +#endif #include <QMimeData> -#ifdef ENABLE_PRINTING +#if QT_CONFIG(webengine_printing_and_pdf) #include <QPrinter> #endif #include <QStandardPaths> @@ -86,17 +100,13 @@ #include <QTimer> #include <QUrl> -#if defined(ENABLE_PRINTING) && defined(ENABLE_PDF) -#include "printing/pdfium_document_wrapper_qt.h" -#endif - QT_BEGIN_NAMESPACE using namespace QtWebEngineCore; static const int MaxTooltipLength = 1024; -#if defined(ENABLE_PRINTING) && defined(ENABLE_PDF) +#if QT_CONFIG(webengine_printing_and_pdf) static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) { if (!data.size()) { @@ -177,7 +187,7 @@ static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) return true; } -#endif // defined(ENABLE_PRINTING) && defined(ENABLE_PDF) +#endif // QT_CONFIG(webengine_printing_and_pdf) static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { @@ -223,7 +233,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , settings(new QWebEngineSettings(profile->settings())) , view(0) , isLoading(false) - , scriptCollection(new QWebEngineScriptCollectionPrivate(browserContextAdapter()->userResourceController(), adapter)) + , scriptCollection(new QWebEngineScriptCollectionPrivate(profileAdapter()->userResourceController(), adapter)) , m_isBeingAdopted(false) , m_backgroundColor(Qt::white) , fullscreenMode(false) @@ -231,7 +241,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , webChannelWorldId(QWebEngineScript::MainWorld) , defaultAudioMuted(false) , defaultZoomFactor(1.0) -#if defined(ENABLE_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) , currentPrinter(nullptr) #endif { @@ -263,17 +273,17 @@ RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostVie // The new delegate will not be deleted by the parent view though, because we unset the parent // when the parent is destroyed. The delegate will be destroyed by Chromium when the popup is // dismissed. - // If the delegate is not for a popup, but for a newly created QWebEngineView, the parent is 0 - // just like before. return new RenderWidgetHostViewQtDelegateWidget(client, this->view); } void QWebEnginePagePrivate::initializationFinished() { if (m_backgroundColor != Qt::white) - adapter->backgroundColorChanged(); + adapter->setBackgroundColor(m_backgroundColor); +#if QT_CONFIG(webengine_webchannel) if (webChannel) adapter->setWebChannel(webChannel, webChannelWorldId); +#endif if (defaultAudioMuted != adapter->isAudioMuted()) adapter->setAudioMuted(defaultAudioMuted); if (!qFuzzyCompare(adapter->currentZoomFactor(), defaultZoomFactor)) @@ -310,7 +320,7 @@ void QWebEnginePagePrivate::iconChanged(const QUrl &url) void QWebEnginePagePrivate::loadProgressChanged(int progress) { Q_Q(QWebEnginePage); - Q_EMIT q->loadProgress(progress); + QTimer::singleShot(0, q, [q, progress] () { Q_EMIT q->loadProgress(progress); }); } void QWebEnginePagePrivate::didUpdateTargetURL(const QUrl &hoveredUrl) @@ -356,12 +366,6 @@ void QWebEnginePagePrivate::loadStarted(const QUrl &provisionalUrl, bool isError isLoading = true; QTimer::singleShot(0, q, &QWebEnginePage::loadStarted); - updateNavigationActions(); -} - -void QWebEnginePagePrivate::loadCommitted() -{ - updateNavigationActions(); } void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription) @@ -389,7 +393,6 @@ void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isE emit q->loadFinished(success); }); } - updateNavigationActions(); } void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success) @@ -498,8 +501,7 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) { -#if defined(ENABLE_PDF) -#if defined(ENABLE_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) // If no currentPrinter is set that means that were printing to PDF only. if (!currentPrinter) { m_callbacks.invoke(requestId, result); @@ -508,16 +510,13 @@ void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &re bool printerResult = printPdfDataOnPrinter(result, *currentPrinter); - m_callbacks.invoke(requestId, printerResult); currentPrinter = nullptr; -#else // If print support is disabled, only PDF printing is available. - m_callbacks.invoke(requestId, result); -#endif // defined(ENABLE_PRINTING) -#else // defined(ENABLE_PDF) + m_callbacks.invoke(requestId, printerResult); +#else // we should never enter this branch, but just for safe-keeping... Q_UNUSED(result); m_callbacks.invoke(requestId, QByteArray()); -#endif // defined(ENABLE_PDF) +#endif } void QWebEnginePagePrivate::passOnFocus(bool reverse) @@ -548,6 +547,7 @@ void QWebEnginePagePrivate::authenticationRequired(QSharedPointer<Authentication void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserController> controller) { +#if QT_CONFIG(colordialog) QColorDialog *dialog = new QColorDialog(controller.data()->initialColor(), view); QColorDialog::connect(dialog, SIGNAL(colorSelected(QColor)), controller.data(), SLOT(accept(QColor))); @@ -558,6 +558,9 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserControlle QColorDialog::connect(dialog, SIGNAL(rejected()), dialog, SLOT(deleteLater())); dialog->open(); +#else + Q_UNUSED(controller); +#endif } void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags) @@ -673,6 +676,8 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input) adapter = std::move(newWebContents); adapter->setClient(this); adapter->loadDefault(); + if (view && view->isVisible()) + wasShown(); } } @@ -696,9 +701,9 @@ void QWebEnginePagePrivate::setFullScreenMode(bool fullscreen) } } -QSharedPointer<BrowserContextAdapter> QWebEnginePagePrivate::browserContextAdapter() +ProfileAdapter* QWebEnginePagePrivate::profileAdapter() { - return profile->d_ptr->browserContext(); + return profile->d_ptr->profileAdapter(); } WebContentsAdapter *QWebEnginePagePrivate::webContentsAdapter() @@ -713,12 +718,87 @@ const QObject *QWebEnginePagePrivate::holdingQObject() const return q; } +void QWebEnginePagePrivate::widgetChanged(RenderWidgetHostViewQtDelegate *newWidgetBase) +{ + Q_Q(QWebEnginePage); + bindPageAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateWidget *>(newWidgetBase)); +} + void QWebEnginePagePrivate::ensureInitialized() const { if (!adapter->isInitialized()) adapter->loadDefault(); } +void QWebEnginePagePrivate::bindPageAndView(QWebEnginePage *page, QWebEngineView *view) +{ + auto oldView = page ? page->d_func()->view : nullptr; + auto oldPage = view ? view->d_func()->page : nullptr; + + // Change pointers first. + + if (page && oldView != view) { + if (oldView) + oldView->d_func()->page = nullptr; + page->d_func()->view = view; + } + + if (view && oldPage != page) { + if (oldPage) + oldPage->d_func()->view = nullptr; + view->d_func()->page = page; + } + + // Then notify. + + auto widget = page ? page->d_func()->widget : nullptr; + auto oldWidget = oldPage ? oldPage->d_func()->widget : nullptr; + + if (page && oldView != view && oldView) { + oldView->d_func()->pageChanged(page, nullptr); + if (widget) + oldView->d_func()->widgetChanged(widget, nullptr); + } + + if (view && oldPage != page) { + view->d_func()->pageChanged(oldPage, page); + if (oldWidget != widget) + view->d_func()->widgetChanged(oldWidget, widget); + } +} + +void QWebEnginePagePrivate::bindPageAndWidget(QWebEnginePage *page, RenderWidgetHostViewQtDelegateWidget *widget) +{ + auto oldPage = widget ? widget->m_page : nullptr; + auto oldWidget = page ? page->d_func()->widget : nullptr; + + // Change pointers first. + + if (widget && oldPage != page) { + if (oldPage) + oldPage->d_func()->widget = nullptr; + widget->m_page = page; + } + + if (page && oldWidget != widget) { + if (oldWidget) + oldWidget->m_page = nullptr; + page->d_func()->widget = widget; + } + + // Then notify. + + if (widget && oldPage != page && oldPage) { + if (auto oldView = oldPage->d_func()->view) + oldView->d_func()->widgetChanged(widget, nullptr); + } + + if (page && oldWidget != widget) { + if (auto view = page->d_func()->view) + view->d_func()->widgetChanged(oldWidget, widget); + } +} + QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(parent) , d_ptr(new QWebEnginePagePrivate()) @@ -729,6 +809,16 @@ QWebEnginePage::QWebEnginePage(QObject* parent) } /*! + \fn void QWebEnginePage::printRequested() + \since 5.12 + + This signal is emitted when the JavaScript \c{window.print()} method is called. + Typically, the signal handler can simply call printToPdf(). + + \sa printToPdf() +*/ + +/*! \enum QWebEnginePage::RenderProcessTerminationStatus \since 5.6 @@ -880,7 +970,8 @@ QWebEnginePage::~QWebEnginePage() Q_D(QWebEnginePage); setDevToolsPage(nullptr); d->adapter->stopFinding(); - QWebEngineViewPrivate::bind(d->view, 0); + QWebEnginePagePrivate::bindPageAndView(this, nullptr); + QWebEnginePagePrivate::bindPageAndWidget(this, nullptr); } QWebEngineHistory *QWebEnginePage::history() const @@ -905,8 +996,12 @@ QWebEngineSettings *QWebEnginePage::settings() const */ QWebChannel *QWebEnginePage::webChannel() const { +#if QT_CONFIG(webengine_webchannel) Q_D(const QWebEnginePage); return d->webChannel; +#endif + qWarning("WebEngine compiled without webchannel support"); + return nullptr; } /*! @@ -943,12 +1038,18 @@ void QWebEnginePage::setWebChannel(QWebChannel *channel) */ void QWebEnginePage::setWebChannel(QWebChannel *channel, uint worldId) { +#if QT_CONFIG(webengine_webchannel) Q_D(QWebEnginePage); if (d->webChannel != channel || d->webChannelWorldId != worldId) { d->webChannel = channel; d->webChannelWorldId = worldId; d->adapter->setWebChannel(channel, worldId); } +#else + Q_UNUSED(channel) + Q_UNUSED(worldId) + qWarning("WebEngine compiled without webchannel support"); +#endif } /*! @@ -975,7 +1076,7 @@ void QWebEnginePage::setBackgroundColor(const QColor &color) if (d->m_backgroundColor == color) return; d->m_backgroundColor = color; - d->adapter->backgroundColorChanged(); + d->adapter->setBackgroundColor(color); } /*! @@ -1039,9 +1140,9 @@ bool QWebEnginePage::recentlyAudible() const return d->adapter->isInitialized() && d->adapter->recentlyAudible(); } -void QWebEnginePage::setView(QWidget *view) +void QWebEnginePage::setView(QWidget *newViewBase) { - QWebEngineViewPrivate::bind(qobject_cast<QWebEngineView*>(view), this); + QWebEnginePagePrivate::bindPageAndView(this, qobject_cast<QWebEngineView *>(newViewBase)); } QWidget *QWebEnginePage::view() const @@ -1543,6 +1644,7 @@ void QWebEnginePagePrivate::wasHidden() void QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData &data) { +#if QT_CONFIG(action) if (!view) return; @@ -1571,6 +1673,9 @@ void QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData } Q_UNREACHABLE(); +#else + Q_UNUSED(data); +#endif // QT_CONFIG(action) } void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) @@ -1616,7 +1721,9 @@ void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogCont accepted = q->javaScriptConfirm(controller->securityOrigin(), QCoreApplication::translate("QWebEnginePage", "Are you sure you want to leave this page? Changes that you made may not be saved.")); break; case InternalAuthorizationDialog: +#if QT_CONFIG(messagebox) accepted = (QMessageBox::question(view, controller->title(), controller->message(), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes); +#endif // QT_CONFIG(messagebox) break; } if (accepted) @@ -1637,6 +1744,36 @@ void QWebEnginePagePrivate::allowCertificateError(const QSharedPointer<Certifica controller->accept(accepted); } +void QWebEnginePagePrivate::selectClientCert(const QSharedPointer<ClientCertSelectController> &controller) +{ +#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + Q_Q(QWebEnginePage); + QWebEngineClientCertificateSelection certSelection(controller); + + Q_EMIT q->selectClientCertificate(certSelection); +#else + Q_UNUSED(controller); +#endif +} + +#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) +/*! + \fn void QWebEnginePage::selectClientCertificate(QWebEngineClientCertificateSelection clientCertificateSelection) + \since 5.12 + + This signal is emitted when a web site requests an SSL client certificate, and one or more were + found in system's client certificate store. + + Handling the signal is asynchronous, and loading will be waiting until a certificate is selected, + or the last copy of \a clientCertificateSelection is destroyed. + + If the signal is not handled, \a clientCertificateSelection is automatically destroyed, and loading + will continue without a client certificate. + + \sa QWebEngineClientCertificateSelection +*/ +#endif + void QWebEnginePagePrivate::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) { Q_Q(QWebEnginePage); @@ -1705,6 +1842,15 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) view->setToolTip(wrappedTip); } +void QWebEnginePagePrivate::printRequested() +{ + Q_Q(QWebEnginePage); + QTimer::singleShot(0, q, [q](){ + Q_EMIT q->printRequested(); + }); +} + +#if QT_CONFIG(menu) QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); @@ -1723,6 +1869,7 @@ QMenu *QWebEnginePage::createStandardContextMenu() return menu; } +#endif // QT_CONFIG(menu) void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) { @@ -2098,6 +2245,7 @@ ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, QWebEnginePage::FileSelec QStringList QWebEnginePage::chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) { +#if QT_CONFIG(filedialog) // FIXME: Should we expose this in QWebPage's API ? Right now it is very open and can contain a mix and match of file extensions (which QFileDialog // can work with) and mimetypes ranging from text/plain or images/* to application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Q_UNUSED(acceptedMimeTypes); @@ -2125,27 +2273,50 @@ QStringList QWebEnginePage::chooseFiles(FileSelectionMode mode, const QStringLis break; } return ret; +#else + Q_UNUSED(mode); + Q_UNUSED(oldFiles); + Q_UNUSED(acceptedMimeTypes); + + return QStringList(); +#endif // QT_CONFIG(filedialog) } void QWebEnginePage::javaScriptAlert(const QUrl &securityOrigin, const QString &msg) { Q_UNUSED(securityOrigin); +#if QT_CONFIG(messagebox) QMessageBox::information(view(), QStringLiteral("Javascript Alert - %1").arg(url().toString()), msg); +#else + Q_UNUSED(msg); +#endif // QT_CONFIG(messagebox) } bool QWebEnginePage::javaScriptConfirm(const QUrl &securityOrigin, const QString &msg) { Q_UNUSED(securityOrigin); +#if QT_CONFIG(messagebox) return (QMessageBox::information(view(), QStringLiteral("Javascript Confirm - %1").arg(url().toString()), msg, QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok); +#else + Q_UNUSED(msg); + return false; +#endif // QT_CONFIG(messagebox) } bool QWebEnginePage::javaScriptPrompt(const QUrl &securityOrigin, const QString &msg, const QString &defaultValue, QString *result) { Q_UNUSED(securityOrigin); +#if QT_CONFIG(inputdialog) bool ret = false; if (result) *result = QInputDialog::getText(view(), QStringLiteral("Javascript Prompt - %1").arg(url().toString()), msg, QLineEdit::Normal, defaultValue, &ret); return ret; +#else + Q_UNUSED(msg); + Q_UNUSED(defaultValue); + Q_UNUSED(result); + return false; +#endif // QT_CONFIG(inputdialog) } void QWebEnginePage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) @@ -2212,20 +2383,18 @@ QSizeF QWebEnginePage::contentsSize() const */ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout) { -#if defined(ENABLE_PDF) +#if QT_CONFIG(webengine_printing_and_pdf) Q_D(const QWebEnginePage); -#if defined(ENABLE_PRINTING) if (d->currentPrinter) { qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); return; } -#endif // ENABLE_PRINTING d->ensureInitialized(); d->adapter->printToPDF(pageLayout, filePath); #else Q_UNUSED(filePath); Q_UNUSED(pageLayout); -#endif // if defined(ENABLE_PDF) +#endif } @@ -2242,21 +2411,19 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout) { Q_D(QWebEnginePage); -#if defined(ENABLE_PDF) -#if defined(ENABLE_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) if (d->currentPrinter) { qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); d->m_callbacks.invokeEmpty(resultCallback); return; } -#endif // ENABLE_PRINTING d->ensureInitialized(); quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.registerCallback(requestId, resultCallback); -#else // if defined(ENABLE_PDF) +#else Q_UNUSED(pageLayout); d->m_callbacks.invokeEmpty(resultCallback); -#endif // if defined(ENABLE_PDF) +#endif } /*! @@ -2279,24 +2446,22 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); -#if defined(ENABLE_PDF) -#if defined(ENABLE_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) if (d->currentPrinter) { qWarning("Cannot print page on printer %ls: Already printing on %ls.", qUtf16Printable(printer->printerName()), qUtf16Printable(d->currentPrinter->printerName())); d->m_callbacks.invokeDirectly(resultCallback, false); return; } d->currentPrinter = printer; -#endif // ENABLE_PRINTING d->ensureInitialized(); quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(), printer->colorMode() == QPrinter::Color, false); d->m_callbacks.registerCallback(requestId, resultCallback); -#else // if defined(ENABLE_PDF) +#else Q_UNUSED(printer); d->m_callbacks.invokeDirectly(resultCallback, false); -#endif // if defined(ENABLE_PDF) +#endif } /*! @@ -2313,6 +2478,7 @@ const QWebEngineContextMenuData &QWebEnginePage::contextMenuData() const return d->contextData; } +#if QT_CONFIG(action) QContextMenuBuilder::QContextMenuBuilder(const QtWebEngineCore::WebEngineContextMenuData &data, QWebEnginePage *page, QMenu *menu) @@ -2480,6 +2646,7 @@ bool QContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) } Q_UNREACHABLE(); } +#endif // QT_CONFIG(action) QT_END_NAMESPACE |