-
Peter Varga authored
[ChangeLog][QtWebEngineQML][QQuickWebEngineView] View Source feature is now supported [ChangeLog][QtWebEngineWidgets][QWebEnginePage] View Source feature is now supported Change-Id: Icc16da71fc6ec95880897fc9744dd8be8c004e00 Reviewed-by:
Allan Sandfeld Jensen <allan.jensen@qt.io>
9b8c1020
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qquickwebengineview_p.h"
#include "qquickwebengineview_p_p.h"
#include "authentication_dialog_controller.h"
#include "browser_context_adapter.h"
#include "certificate_error_controller.h"
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
#include "qquickwebenginehistory_p.h"
#include "qquickwebenginecertificateerror_p.h"
#include "qquickwebenginefaviconprovider_p_p.h"
#include "qquickwebengineloadrequest_p.h"
#include "qquickwebenginenavigationrequest_p.h"
#include "qquickwebenginenewviewrequest_p.h"
#include "qquickwebengineprofile_p.h"
#include "qquickwebenginesettings_p.h"
#include "qquickwebenginescript_p_p.h"
#ifdef ENABLE_QML_TESTSUPPORT_API
#include "qquickwebenginetestsupport_p.h"
#endif
#include "render_widget_host_view_qt_delegate_quick.h"
#include "render_widget_host_view_qt_delegate_quickwindow.h"
#include "ui_delegates_manager.h"
#include "user_resource_controller_host.h"
#include "web_contents_adapter.h"
#include "web_engine_error.h"
#include "web_engine_settings.h"
#include "web_engine_visited_links_manager.h"
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
#include <QClipboard>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QMarginsF>
#include <QMimeData>
#include <QPageLayout>
#include <QPageSize>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlProperty>
#include <QQmlWebChannel>
#include <QQuickWebEngineProfile>
#include <QScreen>
#include <QUrl>
#include <QTimer>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#ifndef QT_NO_ACCESSIBILITY
#include <private/qquickaccessibleattached_p.h>
#endif // QT_NO_ACCESSIBILITY
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
#ifndef QT_NO_ACCESSIBILITY
static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *object)
{
if (QQuickWebEngineView *v = qobject_cast<QQuickWebEngineView*>(object))
return new QQuickWebEngineViewAccessible(v);
return 0;
}
#endif // QT_NO_ACCESSIBILITY
QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
: adapter(0)
, e(new QQuickWebEngineViewExperimental(this))
, v(new QQuickWebEngineViewport(this))
, m_history(new QQuickWebEngineHistory(this))
, m_profile(QQuickWebEngineProfile::defaultProfile())
, m_settings(new QQuickWebEngineSettings(m_profile->settings()))
#ifdef ENABLE_QML_TESTSUPPORT_API
, m_testSupport(0)
#endif
, contextMenuExtraItems(0)
, faviconProvider(0)
, loadProgress(0)
, m_fullscreenMode(false)
, isLoading(false)
, m_activeFocusOnPress(true)
, devicePixelRatio(QGuiApplication::primaryScreen()->devicePixelRatio())
, m_webChannel(0)
, m_webChannelWorld(0)
, m_dpiScale(1.0)
, m_backgroundColor(Qt::white)
, m_defaultZoomFactor(1.0)
// QTBUG-53467
, m_menuEnabled(true)
{
// The gold standard for mobile web content is 160 dpi, and the devicePixelRatio expected
// is the (possibly quantized) ratio of device dpi to 160 dpi.
// However GUI toolkits on non-iOS platforms may be using different criteria than relative
// DPI (depending on the history of that platform), dictating the choice of
// QScreen::devicePixelRatio().
// Where applicable (i.e. non-iOS mobile platforms), override QScreen::devicePixelRatio
// and instead use a reasonable default value for viewport.devicePixelRatio to avoid every
// app having to use this experimental API.
QString platform = qApp->platformName().toLower();
if (platform == QLatin1String("qnx")) {
qreal webPixelRatio = QGuiApplication::primaryScreen()->physicalDotsPerInch() / 160;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
// Quantize devicePixelRatio to increments of 1 to allow JS and media queries to select
// 1x, 2x, 3x etc assets that fit an integral number of pixels.
setDevicePixelRatio(qMax(1, qRound(webPixelRatio)));
}
if (platform == QLatin1Literal("eglfs"))
m_menuEnabled = false;
#ifndef QT_NO_ACCESSIBILITY
QAccessible::installFactory(&webAccessibleFactory);
#endif // QT_NO_ACCESSIBILITY
}
QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate()
{
}
QQuickWebEngineViewExperimental *QQuickWebEngineViewPrivate::experimental() const
{
return e.data();
}
QQuickWebEngineViewport *QQuickWebEngineViewPrivate::viewport() const
{
return v.data();
}
UIDelegatesManager *QQuickWebEngineViewPrivate::ui()
{
Q_Q(QQuickWebEngineView);
if (m_uIDelegatesManager.isNull())
m_uIDelegatesManager.reset(new UIDelegatesManager(q));
return m_uIDelegatesManager.data();
}
RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client)
{
return new RenderWidgetHostViewQtDelegateQuick(client, /*isPopup = */ false);
}
RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegateForPopup(RenderWidgetHostViewQtDelegateClient *client)
{
Q_Q(QQuickWebEngineView);
const bool hasWindowCapability = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
RenderWidgetHostViewQtDelegateQuick *quickDelegate = new RenderWidgetHostViewQtDelegateQuick(client, /*isPopup = */ true);
if (hasWindowCapability) {
RenderWidgetHostViewQtDelegateQuickWindow *wrapperWindow = new RenderWidgetHostViewQtDelegateQuickWindow(quickDelegate);
quickDelegate->setParentItem(wrapperWindow->contentItem());
return wrapperWindow;
}
quickDelegate->setParentItem(q);
return quickDelegate;
}
bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenuData &data)
{
Q_Q(QQuickWebEngineView);
if (!m_menuEnabled) {
qWarning("You are trying to open context menu on eglfs backend, which is not currently supported\n"
"See QTBUG-53467.");
return false;
}
// Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated
// on OSX.
QObject *menu = ui()->addMenu(q, QString(), data.pos);
if (!menu)
return false;
contextMenuData.update(data);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
Q_EMIT q->experimental()->contextMenuDataChanged();
// Populate our menu
MenuItemHandler *item = 0;
if (contextMenuData.isContentEditable() && !contextMenuData.spellCheckerSuggestions().isEmpty()) {
const QPointer<QQuickWebEngineView> qRef(q);
for (int i=0; i < contextMenuData.spellCheckerSuggestions().count() && i < 4; i++) {
item = new MenuItemHandler(menu);
QString replacement = contextMenuData.spellCheckerSuggestions().at(i);
QObject::connect(item, &MenuItemHandler::triggered, [qRef, replacement] { qRef->replaceMisspelledWord(replacement); });
ui()->addMenuItem(item, replacement);
}
ui()->addMenuSeparator(menu);
}
if (!data.linkText.isEmpty() && data.linkUrl.isValid()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::OpenLinkInThisWindow); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Follow Link"));
}
if (data.selectedText.isEmpty()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goBack);
ui()->addMenuItem(item, QQuickWebEngineView::tr("Back"), QStringLiteral("go-previous"), q->canGoBack());
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goForward);
ui()->addMenuItem(item, QQuickWebEngineView::tr("Forward"), QStringLiteral("go-next"), q->canGoForward());
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::reload);
ui()->addMenuItem(item, QQuickWebEngineView::tr("Reload"), QStringLiteral("view-refresh"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::viewSource);
ui()->addMenuItem(item, QQuickWebEngineView::tr("View Page Source"), QStringLiteral("view-source"), q->canViewSource());
} else {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Copy); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Unselect); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Unselect"));
}
if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Link URL"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Link"));
}
if (contextMenuData.mediaUrl().isValid()) {
switch (contextMenuData.mediaType()) {
case QQuickWebEngineContextMenuData::MediaTypeImage:
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image URL"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Image"));
break;
case QQuickWebEngineContextMenuData::MediaTypeCanvas:
Q_UNREACHABLE(); // mediaUrl is invalid for canvases
break;
case QQuickWebEngineContextMenuData::MediaTypeAudio:
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
case QQuickWebEngineContextMenuData::MediaTypeVideo:
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Media URL"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadMediaToDisk); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Media"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaPlayPause); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Play/Pause"));
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Looping"));
if (data.mediaFlags & WebEngineContextMenuData::MediaHasAudio) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaMute); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Mute"));
}
if (data.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Media Controls"));
}
break;
default:
break;
}
} else if (contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeCanvas) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image"));
}
if (adapter->hasInspector()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::InspectElement); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Inspect Element"));
}
if (isFullScreenMode()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ExitFullScreen); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Exit Full Screen Mode"));
}
// FIXME: expose the context menu data as an attached property to make this more useful
if (contextMenuExtraItems) {
ui()->addMenuSeparator(menu);
if (QObject* menuExtras = contextMenuExtraItems->create(qmlContext(q))) {
menuExtras->setParent(menu);
QQmlListReference entries(menu, defaultPropertyName(menu), qmlEngine(q));
if (entries.isValid())
entries.append(menuExtras);
}
}
// Now fire the popup() method on the top level menu
QMetaObject::invokeMethod(menu, "popup");
return true;
}
void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame)
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineNavigationRequest navigationRequest(url, static_cast<QQuickWebEngineView::NavigationType>(navigationType), isMainFrame);
Q_EMIT q->navigationRequested(&navigationRequest);
navigationRequestAction = navigationRequest.action();
}
void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog)
{
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
ui()->showDialog(dialog);
}
void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController)
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineCertificateError *quickController = new QQuickWebEngineCertificateError(errorController);
QQmlEngine::setObjectOwnership(quickController, QQmlEngine::JavaScriptOwnership);
Q_EMIT q->certificateError(quickController);
if (!quickController->deferred() && !quickController->answered())
quickController->rejectCertificate();
else
m_certificateErrorControllers.append(errorController);
}
void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->featurePermissionRequested(url, QQuickWebEngineView::Geolocation);
}
void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
{
ui()->showColorDialog(controller);
}
void QQuickWebEngineViewPrivate::runFileChooser(FilePickerController* controller)
{
ui()->showFilePicker(controller);
}
void QQuickWebEngineViewPrivate::passOnFocus(bool reverse)
{
Q_Q(QQuickWebEngineView);
// The child delegate currently has focus, find the next one from there and give it focus.
QQuickItem *next = q->scopedFocusItem()->nextItemInFocusChain(!reverse);
next->forceActiveFocus(reverse ? Qt::BacktabFocusReason : Qt::TabFocusReason);
}
void QQuickWebEngineViewPrivate::titleChanged(const QString &title)
{
Q_Q(QQuickWebEngineView);
Q_UNUSED(title);
Q_EMIT q->titleChanged();
}
void QQuickWebEngineViewPrivate::urlChanged(const QUrl &url)
{
Q_Q(QQuickWebEngineView);
Q_UNUSED(url);
explicitUrl = QUrl();
Q_EMIT q->urlChanged();
}
void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url)
{
Q_Q(QQuickWebEngineView);
if (iconUrl == QQuickWebEngineFaviconProvider::faviconProviderUrl(url))
return;
if (!faviconProvider) {
QQmlEngine *engine = qmlEngine(q);
Q_ASSERT(engine);
faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>(
engine->imageProvider(QQuickWebEngineFaviconProvider::identifier()));
Q_ASSERT(faviconProvider);
}
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
iconUrl = faviconProvider->attach(q, url);
m_history->reset();
Q_EMIT q->iconChanged();
}
void QQuickWebEngineViewPrivate::loadProgressChanged(int progress)
{
Q_Q(QQuickWebEngineView);
loadProgress = progress;
Q_EMIT q->loadProgressChanged();
}
void QQuickWebEngineViewPrivate::didUpdateTargetURL(const QUrl &hoveredUrl)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->linkHovered(hoveredUrl);
}
void QQuickWebEngineViewPrivate::recentlyAudibleChanged(bool recentlyAudible)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->recentlyAudibleChanged(recentlyAudible);
}
QRectF QQuickWebEngineViewPrivate::viewportRect() const
{
Q_Q(const QQuickWebEngineView);
return QRectF(q->x(), q->y(), q->width(), q->height());
}
qreal QQuickWebEngineViewPrivate::dpiScale() const
{
return m_dpiScale;
}
QColor QQuickWebEngineViewPrivate::backgroundColor() const
{
return m_backgroundColor;
}
void QQuickWebEngineViewPrivate::loadStarted(const QUrl &provisionalUrl, bool isErrorPage)
{
Q_Q(QQuickWebEngineView);
if (isErrorPage) {
#ifdef ENABLE_QML_TESTSUPPORT_API
if (m_testSupport)
m_testSupport->errorPage()->loadStarted(provisionalUrl);
#endif
return;
}
isLoading = true;
m_history->reset();
m_certificateErrorControllers.clear();
QQuickWebEngineLoadRequest loadRequest(provisionalUrl, QQuickWebEngineView::LoadStartedStatus);
Q_EMIT q->loadingChanged(&loadRequest);
}
void QQuickWebEngineViewPrivate::loadCommitted()
{
m_history->reset();
}
void QQuickWebEngineViewPrivate::loadVisuallyCommitted()
{
#ifdef ENABLE_QML_TESTSUPPORT_API
if (m_testSupport)
Q_EMIT m_testSupport->loadVisuallyCommitted();
#endif
}
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
Q_STATIC_ASSERT(static_cast<int>(WebEngineError::NoErrorDomain) == static_cast<int>(QQuickWebEngineView::NoErrorDomain));
Q_STATIC_ASSERT(static_cast<int>(WebEngineError::CertificateErrorDomain) == static_cast<int>(QQuickWebEngineView::CertificateErrorDomain));
Q_STATIC_ASSERT(static_cast<int>(WebEngineError::DnsErrorDomain) == static_cast<int>(QQuickWebEngineView::DnsErrorDomain));
void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription)
{
Q_Q(QQuickWebEngineView);
if (isErrorPage) {
#ifdef ENABLE_QML_TESTSUPPORT_API
if (m_testSupport)
m_testSupport->errorPage()->loadFinished(success, url);
#endif
return;
}
isLoading = false;
m_history->reset();
if (errorCode == WebEngineError::UserAbortedError) {
QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadStoppedStatus);
Q_EMIT q->loadingChanged(&loadRequest);
return;
}
if (success) {
explicitUrl = QUrl();
QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus);
Q_EMIT q->loadingChanged(&loadRequest);
return;
}
Q_ASSERT(errorCode);
QQuickWebEngineLoadRequest loadRequest(
url,
QQuickWebEngineView::LoadFailedStatus,
errorDescription,
errorCode,
static_cast<QQuickWebEngineView::ErrorDomain>(WebEngineError::toQtErrorDomain(errorCode)));
Q_EMIT q->loadingChanged(&loadRequest);
return;
}
void QQuickWebEngineViewPrivate::focusContainer()
{
Q_Q(QQuickWebEngineView);
q->forceActiveFocus();
}
void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event)
{
Q_Q(QQuickWebEngineView);
if (q->parentItem())
q->window()->sendEvent(q->parentItem(), event);
}
void QQuickWebEngineViewPrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &)
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineNewViewRequest request;
// This increases the ref-count of newWebContents and will tell Chromium
// to start loading it and possibly return it to its parent page window.open().
request.m_adapter = newWebContents;
request.m_isUserInitiated = userGesture;
switch (disposition) {
case WebContentsAdapterClient::NewForegroundTabDisposition:
request.m_destination = QQuickWebEngineView::NewViewInTab;
break;
case WebContentsAdapterClient::NewBackgroundTabDisposition:
request.m_destination = QQuickWebEngineView::NewViewInBackgroundTab;
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
break;
case WebContentsAdapterClient::NewPopupDisposition:
request.m_destination = QQuickWebEngineView::NewViewInDialog;
break;
case WebContentsAdapterClient::NewWindowDisposition:
request.m_destination = QQuickWebEngineView::NewViewInWindow;
break;
default:
Q_UNREACHABLE();
}
Q_EMIT q->newViewRequested(&request);
}
bool QQuickWebEngineViewPrivate::isBeingAdopted()
{
return false;
}
void QQuickWebEngineViewPrivate::close()
{
Q_Q(QQuickWebEngineView);
emit q->windowCloseRequested();
}
void QQuickWebEngineViewPrivate::windowCloseRejected()
{
#ifdef ENABLE_QML_TESTSUPPORT_API
if (m_testSupport)
Q_EMIT m_testSupport->windowCloseRejected();
#endif
}
void QQuickWebEngineViewPrivate::requestFullScreenMode(const QUrl &origin, bool fullscreen)
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineFullScreenRequest request(this, origin, fullscreen);
Q_EMIT q->fullScreenRequested(request);
}
bool QQuickWebEngineViewPrivate::isFullScreenMode() const
{
return m_fullscreenMode;
}
void QQuickWebEngineViewPrivate::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID)
{
Q_Q(QQuickWebEngineView);
if (q->receivers(SIGNAL(javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString))) > 0) {
Q_EMIT q->javaScriptConsoleMessage(static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(level), message, lineNumber, sourceID);
return;
}
static QLoggingCategory loggingCategory("js", QtWarningMsg);
const QByteArray file = sourceID.toUtf8();
QMessageLogger logger(file.constData(), lineNumber, nullptr, loggingCategory.categoryName());
switch (level) {
case JavaScriptConsoleMessageLevel::Info:
if (loggingCategory.isInfoEnabled())
logger.info().noquote() << message;
break;
case JavaScriptConsoleMessageLevel::Warning:
if (loggingCategory.isWarningEnabled())
logger.warning().noquote() << message;
break;
case JavaScriptConsoleMessageLevel::Error:
if (loggingCategory.isCriticalEnabled())
logger.critical().noquote() << message;
break;
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
}
}
void QQuickWebEngineViewPrivate::authenticationRequired(QSharedPointer<AuthenticationDialogController> controller)
{
ui()->showDialog(controller);
}
void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags)
{
Q_Q(QQuickWebEngineView);
if (!requestFlags)
return;
QQuickWebEngineView::Feature feature;
if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture))
feature = QQuickWebEngineView::MediaAudioVideoCapture;
else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture))
feature = QQuickWebEngineView::MediaAudioCapture;
else // WebContentsAdapterClient::MediaVideoCapture
feature = QQuickWebEngineView::MediaVideoCapture;
Q_EMIT q->featurePermissionRequested(securityOrigin, feature);
}
void QQuickWebEngineViewPrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin)
{
Q_UNUSED(securityOrigin);
// TODO: Add mouse lock support
adapter->grantMouseLockPermission(false);
}
#ifndef QT_NO_ACCESSIBILITY
QObject *QQuickWebEngineViewPrivate::accessibilityParentObject()
{
Q_Q(QQuickWebEngineView);
return q;
}
#endif // QT_NO_ACCESSIBILITY
QSharedPointer<BrowserContextAdapter> QQuickWebEngineViewPrivate::browserContextAdapter()
{
return m_profile->d_ptr->browserContext();
}
WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter()
{
return adapter.data();
}
WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const
{
return m_settings->d_ptr.data();
}
const QObject *QQuickWebEngineViewPrivate::holdingQObject() const
{
Q_Q(const QQuickWebEngineView);
return q;
}
void QQuickWebEngineViewPrivate::setDevicePixelRatio(qreal devicePixelRatio)
{
Q_Q(QQuickWebEngineView);
this->devicePixelRatio = devicePixelRatio;
QScreen *screen = q->window() ? q->window()->screen() : QGuiApplication::primaryScreen();
m_dpiScale = devicePixelRatio / screen->devicePixelRatio();
}
#ifndef QT_NO_ACCESSIBILITY
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
QQuickWebEngineViewAccessible::QQuickWebEngineViewAccessible(QQuickWebEngineView *o)
: QAccessibleObject(o)
{}
QAccessibleInterface *QQuickWebEngineViewAccessible::parent() const
{
QQuickItem *parent = engineView()->parentItem();
return QAccessible::queryAccessibleInterface(parent);
}
int QQuickWebEngineViewAccessible::childCount() const
{
if (engineView() && child(0))
return 1;
return 0;
}
QAccessibleInterface *QQuickWebEngineViewAccessible::child(int index) const
{
if (index == 0)
return engineView()->d_func()->adapter->browserAccessible();
return 0;
}
int QQuickWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const
{
if (c == child(0))
return 0;
return -1;
}
QString QQuickWebEngineViewAccessible::text(QAccessible::Text) const
{
return QString();
}
QAccessible::Role QQuickWebEngineViewAccessible::role() const
{
return QAccessible::Document;
}
QAccessible::State QQuickWebEngineViewAccessible::state() const
{
QAccessible::State s;
return s;
}
#endif // QT_NO_ACCESSIBILITY
class WebContentsAdapterOwner : public QObject
{
public:
typedef QExplicitlySharedDataPointer<QtWebEngineCore::WebContentsAdapter> AdapterPtr;
WebContentsAdapterOwner(const AdapterPtr &ptr)
: adapter(ptr)
{}
private:
AdapterPtr adapter;
};
void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContents)
{
if (!webContents) {
qWarning("Trying to open an empty request, it was either already used or was invalidated."
"\nYou must complete the request synchronously within the newViewRequested signal handler."
" If a view hasn't been adopted before returning, the request will be invalidated.");
return;
}
if (webContents->browserContextAdapter() && browserContextAdapter() != webContents->browserContextAdapter()) {
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
qWarning("Can not adopt content from a different WebEngineProfile.");
return;
}
Q_Q(QQuickWebEngineView);
// This throws away the WebContentsAdapter that has been used until now.
// All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter.
WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter);
adapterOwner->deleteLater();
adapter = webContents;
adapter->initialize(this);
// associate the webChannel with the new adapter
if (m_webChannel)
adapter->setWebChannel(m_webChannel, m_webChannelWorld);
// set initial background color if non-default
if (m_backgroundColor != Qt::white)
adapter->backgroundColorChanged();
// re-bind the userscrips to the new adapter
Q_FOREACH (QQuickWebEngineScript *script, m_userScripts)
script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data());
// set the zoomFactor if it had been changed on the old adapter.
if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor))
q->setZoomFactor(m_defaultZoomFactor);
// Emit signals for values that might be different from the previous WebContentsAdapter.
emit q->titleChanged();
emit q->urlChanged();
emit q->iconChanged();
// FIXME: The current loading state should be stored in the WebContentAdapter
// and it should be checked here if the signal emission is really necessary.
QQuickWebEngineLoadRequest loadRequest(adapter->activeUrl(), QQuickWebEngineView::LoadSucceededStatus);
emit q->loadingChanged(&loadRequest);
emit q->loadProgressChanged();
}
QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent)
: QQuickItem(parent)
, d_ptr(new QQuickWebEngineViewPrivate)
{
Q_D(QQuickWebEngineView);
d->e->q_ptr = d->q_ptr = this;
this->setActiveFocusOnTab(true);
this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsInputMethod
| QQuickItem::ItemAcceptsDrops);
#ifndef QT_NO_ACCESSIBILITY
QQuickAccessibleAttached *accessible = QQuickAccessibleAttached::qmlAttachedProperties(this);
accessible->setRole(QAccessible::Grouping);
#endif // QT_NO_ACCESSIBILITY
}
QQuickWebEngineView::~QQuickWebEngineView()
{
Q_D(QQuickWebEngineView);
if (d->faviconProvider)
d->faviconProvider->detach(this);
}
void QQuickWebEngineViewPrivate::ensureContentsAdapter()
{
Q_Q(QQuickWebEngineView);
if (!adapter) {
adapter = new WebContentsAdapter();
adapter->initialize(this);
if (m_backgroundColor != Qt::white)
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
adapter->backgroundColorChanged();
if (m_webChannel)
adapter->setWebChannel(m_webChannel, m_webChannelWorld);
if (explicitUrl.isValid())
adapter->load(explicitUrl);
// push down the page's user scripts
Q_FOREACH (QQuickWebEngineScript *script, m_userScripts)
script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data());
// set the zoomFactor if it had been changed on the old adapter.
if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor))
q->setZoomFactor(m_defaultZoomFactor);
}
}
void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen)
{
Q_Q(QQuickWebEngineView);
if (m_fullscreenMode != fullscreen) {
m_fullscreenMode = fullscreen;
adapter->changedFullScreen();
Q_EMIT q->isFullScreenChanged();
}
}
QUrl QQuickWebEngineView::url() const
{
Q_D(const QQuickWebEngineView);
return d->explicitUrl.isValid() ? d->explicitUrl : (d->adapter ? d->adapter->activeUrl() : QUrl());
}
void QQuickWebEngineView::setUrl(const QUrl& url)
{
if (url.isEmpty())
return;
Q_D(QQuickWebEngineView);
d->explicitUrl = url;
if (d->adapter)
d->adapter->load(url);
if (!qmlEngine(this) || isComponentComplete())
d->ensureContentsAdapter();
}
QUrl QQuickWebEngineView::icon() const
{
Q_D(const QQuickWebEngineView);
return d->iconUrl;
}
void QQuickWebEngineView::loadHtml(const QString &html, const QUrl &baseUrl)
{
Q_D(QQuickWebEngineView);
d->explicitUrl = QUrl();
if (!qmlEngine(this) || isComponentComplete())
d->ensureContentsAdapter();
if (d->adapter)
d->adapter->setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl);
}
void QQuickWebEngineView::goBack()
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
d->adapter->navigateToOffset(-1);
}
void QQuickWebEngineView::goForward()
{
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
d->adapter->navigateToOffset(1);
}
void QQuickWebEngineView::reload()
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
d->adapter->reload();
}
void QQuickWebEngineView::reloadAndBypassCache()
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
d->adapter->reloadAndBypassCache();
}
void QQuickWebEngineView::stop()
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
d->adapter->stop();
}
void QQuickWebEngineView::setZoomFactor(qreal arg)
{
Q_D(QQuickWebEngineView);
d->m_defaultZoomFactor = arg;
if (!d->adapter)
return;
qreal oldFactor = d->adapter->currentZoomFactor();
d->adapter->setZoomFactor(arg);
if (qFuzzyCompare(oldFactor, d->adapter->currentZoomFactor()))
return;
emit zoomFactorChanged(arg);
}
QQuickWebEngineProfile *QQuickWebEngineView::profile() const
{
Q_D(const QQuickWebEngineView);
return d->m_profile;
}
void QQuickWebEngineView::setProfile(QQuickWebEngineProfile *profile)
{
Q_D(QQuickWebEngineView);
d->setProfile(profile);
}
QQuickWebEngineSettings *QQuickWebEngineView::settings() const
{
Q_D(const QQuickWebEngineView);
return d->m_settings.data();
}
QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineView::userScripts()
{
Q_D(QQuickWebEngineView);
return QQmlListProperty<QQuickWebEngineScript>(this, d,
d->userScripts_append,
d->userScripts_count,
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
d->userScripts_at,
d->userScripts_clear);
}
void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile)
{
Q_Q(QQuickWebEngineView);
if (profile == m_profile)
return;
m_profile = profile;
Q_EMIT q->profileChanged();
m_settings->setParentSettings(profile->settings());
if (adapter && adapter->browserContext() != browserContextAdapter()->browserContext()) {
// When the profile changes we need to create a new WebContentAdapter and reload the active URL.
QUrl activeUrl = adapter->activeUrl();
adapter = 0;
ensureContentsAdapter();
if (!explicitUrl.isValid() && activeUrl.isValid())
adapter->load(activeUrl);
}
}
#ifdef ENABLE_QML_TESTSUPPORT_API
QQuickWebEngineTestSupport *QQuickWebEngineView::testSupport() const
{
Q_D(const QQuickWebEngineView);
return d->m_testSupport;
}
void QQuickWebEngineView::setTestSupport(QQuickWebEngineTestSupport *testSupport)
{
Q_D(QQuickWebEngineView);
d->m_testSupport = testSupport;
}
#endif
/*!
* \qmlproperty bool WebEngineView::activeFocusOnPress
* \since QtWebEngine 1.2
*
* This property specifies whether the view should gain active focus when pressed.
* The default value is true.
*
*/
bool QQuickWebEngineView::activeFocusOnPress() const
{
Q_D(const QQuickWebEngineView);
return d->m_activeFocusOnPress;
}
void QQuickWebEngineViewPrivate::didRunJavaScript(quint64 requestId, const QVariant &result)
{
Q_Q(QQuickWebEngineView);
QJSValue callback = m_callbacks.take(requestId);
QJSValueList args;
args.append(qmlEngine(q)->toScriptValue(result));
callback.call(args);
}
void QQuickWebEngineViewPrivate::didFindText(quint64 requestId, int matchCount)
{
QJSValue callback = m_callbacks.take(requestId);
QJSValueList args;
args.append(QJSValue(matchCount));
callback.call(args);
}
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, const QByteArray &result)
{
QJSValue callback = m_callbacks.take(requestId);
QJSValueList args;
args.append(QJSValue(result.data()));
callback.call(args);
}
void QQuickWebEngineViewPrivate::showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText)
{
#ifdef ENABLE_QML_TESTSUPPORT_API
if (m_testSupport)
Q_EMIT m_testSupport->validationMessageShown(mainText, subText);
#endif
ui()->showMessageBubble(anchor, mainText, subText);
}
void QQuickWebEngineViewPrivate::hideValidationMessage()
{
ui()->hideMessageBubble();
}
void QQuickWebEngineViewPrivate::moveValidationMessage(const QRect &anchor)
{
ui()->moveMessageBubble(anchor);
}
void QQuickWebEngineViewPrivate::updateScrollPosition(const QPointF &position)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->scrollPositionChanged(position);
}
void QQuickWebEngineViewPrivate::updateContentsSize(const QSizeF &size)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->contentsSizeChanged(size);
}
void QQuickWebEngineViewPrivate::renderProcessTerminated(
RenderProcessTerminationStatus terminationStatus, int exitCode)
{
Q_Q(QQuickWebEngineView);
Q_EMIT q->renderProcessTerminated(static_cast<QQuickWebEngineView::RenderProcessTerminationStatus>(
renderProcessExitStatus(terminationStatus)), exitCode);
}
void QQuickWebEngineViewPrivate::startDragging(const content::DropData &dropData,
Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset)
{
adapter->startDragging(q_ptr->window(), dropData, allowedActions, pixmap, offset);
}
bool QQuickWebEngineViewPrivate::isEnabled() const
{
const Q_Q(QQuickWebEngineView);
return q->isEnabled();
}
void QQuickWebEngineViewPrivate::setToolTip(const QString &toolTipText)
{
ui()->showToolTip(toolTipText);
}
bool QQuickWebEngineView::isLoading() const
{
Q_D(const QQuickWebEngineView);
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
return d->isLoading;
}
int QQuickWebEngineView::loadProgress() const
{
Q_D(const QQuickWebEngineView);
return d->loadProgress;
}
QString QQuickWebEngineView::title() const
{
Q_D(const QQuickWebEngineView);
if (!d->adapter)
return QString();
return d->adapter->pageTitle();
}
bool QQuickWebEngineView::canGoBack() const
{
Q_D(const QQuickWebEngineView);
if (!d->adapter)
return false;
return d->adapter->canGoBack();
}
bool QQuickWebEngineView::canGoForward() const
{
Q_D(const QQuickWebEngineView);
if (!d->adapter)
return false;
return d->adapter->canGoForward();
}
void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &callback)
{
Q_D(QQuickWebEngineView);
d->ensureContentsAdapter();
if (!callback.isUndefined()) {
quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, QQuickWebEngineScript::MainWorld);
d->m_callbacks.insert(requestId, callback);
} else
d->adapter->runJavaScript(script, QQuickWebEngineScript::MainWorld);
}
void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback)
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
if (!callback.isUndefined()) {
quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, worldId);
d->m_callbacks.insert(requestId, callback);
} else
d->adapter->runJavaScript(script, worldId);
}
QQuickWebEngineViewExperimental *QQuickWebEngineView::experimental() const
{
Q_D(const QQuickWebEngineView);
return d->e.data();
}
qreal QQuickWebEngineView::zoomFactor() const
{
Q_D(const QQuickWebEngineView);
if (!d->adapter)
return d->m_defaultZoomFactor;
return d->adapter->currentZoomFactor();
}
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
/*!
\qmlproperty bool WebEngineView::backgroundColor
\since QtWebEngine 1.2
Sets this property to change the color of the WebEngineView's background,
behing the document's body. You can set it to "transparent" or to a translucent
color to see through the document, or you can set this color to match your
web content in an hybrid app to prevent the white flashes that may appear
during loading.
The default value is white.
*/
QColor QQuickWebEngineView::backgroundColor() const
{
Q_D(const QQuickWebEngineView);
return d->m_backgroundColor;
}
void QQuickWebEngineView::setBackgroundColor(const QColor &color)
{
Q_D(QQuickWebEngineView);
if (color == d->m_backgroundColor)
return;
d->m_backgroundColor = color;
if (d->adapter)
d->adapter->backgroundColorChanged();
emit backgroundColorChanged();
}
/*!
\property QQuickWebEngineView::audioMuted
\brief the state of whether the current page audio is muted.
\since 5.7
The default value is false.
*/
bool QQuickWebEngineView::isAudioMuted() const
{
const Q_D(QQuickWebEngineView);
if (d->adapter)
return d->adapter->isAudioMuted();
return false;
}
void QQuickWebEngineView::setAudioMuted(bool muted)
{
Q_D(QQuickWebEngineView);
bool _isAudioMuted = isAudioMuted();
if (d->adapter) {
d->adapter->setAudioMuted(muted);
if (_isAudioMuted != muted) {
Q_EMIT audioMutedChanged(muted);
}
}
}
bool QQuickWebEngineView::recentlyAudible() const
{
const Q_D(QQuickWebEngineView);
if (d->adapter)
return d->adapter->recentlyAudible();
return false;
}
void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation)
{
Q_D(const QQuickWebEngineView);
QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId));
QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation);
QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0));
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
d->adapter->printToPDF(pageLayout, filePath);
}
void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation)
{
Q_D(QQuickWebEngineView);
QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId));
QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation);
QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0));
if (callback.isUndefined())
return;
quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout);
d->m_callbacks.insert(requestId, callback);
}
void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement)
{
Q_D(QQuickWebEngineView);
d->adapter->replaceMisspelling(replacement);
}
void QQuickWebEngineView::viewSource()
{
Q_D(QQuickWebEngineView);
d->adapter->viewSource();
}
bool QQuickWebEngineView::canViewSource() const
{
Q_D(const QQuickWebEngineView);
return d->adapter->canViewSource();
}
bool QQuickWebEngineView::isFullScreen() const
{
Q_D(const QQuickWebEngineView);
return d->m_fullscreenMode;
}
void QQuickWebEngineViewExperimental::setExtraContextMenuEntriesComponent(QQmlComponent *contextMenuExtras)
{
if (d_ptr->contextMenuExtraItems == contextMenuExtras)
return;
d_ptr->contextMenuExtraItems = contextMenuExtras;
emit extraContextMenuEntriesComponentChanged();
}
QQmlComponent *QQuickWebEngineViewExperimental::extraContextMenuEntriesComponent() const
{
return d_ptr->contextMenuExtraItems;
}
void QQuickWebEngineView::findText(const QString &subString, FindFlags options, const QJSValue &callback)
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
if (subString.isEmpty()) {
d->adapter->stopFinding();
if (!callback.isUndefined()) {
QJSValueList args;
args.append(QJSValue(0));
const_cast<QJSValue&>(callback).call(args);
}
} else {
quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward);
if (!callback.isUndefined())
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
d->m_callbacks.insert(requestId, callback);
}
}
QQuickWebEngineHistory *QQuickWebEngineView::navigationHistory() const
{
Q_D(const QQuickWebEngineView);
return d->m_history.data();
}
QQmlWebChannel *QQuickWebEngineView::webChannel()
{
Q_D(QQuickWebEngineView);
if (!d->m_webChannel) {
d->m_webChannel = new QQmlWebChannel(this);
if (d->adapter)
d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld);
}
return d->m_webChannel;
}
void QQuickWebEngineView::setWebChannel(QQmlWebChannel *webChannel)
{
Q_D(QQuickWebEngineView);
if (d->m_webChannel == webChannel)
return;
d->m_webChannel = webChannel;
if (d->adapter)
d->adapter->setWebChannel(webChannel, d->m_webChannelWorld);
Q_EMIT webChannelChanged();
}
uint QQuickWebEngineView::webChannelWorld() const
{
Q_D(const QQuickWebEngineView);
return d->m_webChannelWorld;
}
void QQuickWebEngineView::setWebChannelWorld(uint webChannelWorld)
{
Q_D(QQuickWebEngineView);
if (d->m_webChannelWorld == webChannelWorld)
return;
d->m_webChannelWorld = webChannelWorld;
if (d->adapter)
d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld);
Q_EMIT webChannelWorldChanged(webChannelWorld);
}
void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted)
{
if (!d_ptr->adapter)
return;
if (!granted && feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) {
d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone);
return;
}
switch (feature) {
case MediaAudioCapture:
d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture);
break;
case MediaVideoCapture:
d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture);
break;
case MediaAudioVideoCapture:
d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaAudioCapture | WebContentsAdapterClient::MediaVideoCapture));
break;
case Geolocation:
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
d_ptr->adapter->runGeolocationRequestCallback(securityOrigin, granted);
break;
default:
Q_UNREACHABLE();
}
}
void QQuickWebEngineView::setActiveFocusOnPress(bool arg)
{
Q_D(QQuickWebEngineView);
if (d->m_activeFocusOnPress == arg)
return;
d->m_activeFocusOnPress = arg;
emit activeFocusOnPressChanged(arg);
}
void QQuickWebEngineView::goBackOrForward(int offset)
{
Q_D(QQuickWebEngineView);
if (!d->adapter)
return;
const int current = d->adapter->currentNavigationEntryIndex();
const int count = d->adapter->navigationEntryCount();
const int index = current + offset;
if (index < 0 || index >= count)
return;
d->adapter->navigateToIndex(index);
}
void QQuickWebEngineView::fullScreenCancelled()
{
Q_D(QQuickWebEngineView);
d->adapter->exitFullScreen();
}
void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
QQuickItem::geometryChanged(newGeometry, oldGeometry);
Q_FOREACH(QQuickItem *child, childItems()) {
if (qobject_cast<RenderWidgetHostViewQtDelegateQuick *>(child))
child->setSize(newGeometry.size());
}
}
void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QQuickWebEngineView);
if (d->adapter && (change == ItemSceneChange || change == ItemVisibleHasChanged)) {
if (window() && isVisible())
d->adapter->wasShown();
else
d->adapter->wasHidden();
}
QQuickItem::itemChange(change, value);
}
static QPoint mapToScreen(const QQuickItem *item, const QPoint &clientPos)
{
return item->window()->position() + item->mapToScene(clientPos).toPoint();
}
void QQuickWebEngineView::dragEnterEvent(QDragEnterEvent *e)
{
Q_D(QQuickWebEngineView);
e->accept();
d->adapter->enterDrag(e, mapToScreen(this, e->pos()));
}
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
void QQuickWebEngineView::dragLeaveEvent(QDragLeaveEvent *e)
{
Q_D(QQuickWebEngineView);
e->accept();
d->adapter->leaveDrag();
}
void QQuickWebEngineView::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QQuickWebEngineView);
e->accept();
d->adapter->updateDragPosition(e, mapToScreen(this, e->pos()));
}
void QQuickWebEngineView::dropEvent(QDropEvent *e)
{
Q_D(QQuickWebEngineView);
e->accept();
d->adapter->endDragging(e->pos(), mapToScreen(this, e->pos()));
}
void QQuickWebEngineView::triggerWebAction(WebAction action)
{
Q_D(QQuickWebEngineView);
switch (action) {
case Back:
d->adapter->navigateToOffset(-1);
break;
case Forward:
d->adapter->navigateToOffset(1);
break;
case Stop:
d->adapter->stop();
break;
case Reload:
d->adapter->reload();
break;
case ReloadAndBypassCache:
d->adapter->reloadAndBypassCache();
break;
case Cut:
d->adapter->cut();
break;
case Copy:
d->adapter->copy();
break;
case Paste:
d->adapter->paste();
break;
case Undo:
d->adapter->undo();
break;
case Redo:
d->adapter->redo();
break;
case SelectAll:
d->adapter->selectAll();
break;
case PasteAndMatchStyle:
d->adapter->pasteAndMatchStyle();
break;
case Unselect:
d->adapter->unselect();
break;
case OpenLinkInThisWindow:
if (d->contextMenuData.linkUrl().isValid())
setUrl(d->contextMenuData.linkUrl());
break;
case OpenLinkInNewWindow:
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
if (d->contextMenuData.linkUrl().isValid()) {
QQuickWebEngineNewViewRequest request;
request.m_requestedUrl = d->contextMenuData.linkUrl();
request.m_isUserInitiated = true;
request.m_destination = NewViewInWindow;
Q_EMIT newViewRequested(&request);
}
break;
case OpenLinkInNewTab:
if (d->contextMenuData.linkUrl().isValid()) {
QQuickWebEngineNewViewRequest request;
request.m_requestedUrl = d->contextMenuData.linkUrl();
request.m_isUserInitiated = true;
request.m_destination = NewViewInBackgroundTab;
Q_EMIT newViewRequested(&request);
}
break;
case CopyLinkToClipboard:
if (d->contextMenuData.linkUrl().isValid()) {
QString urlString = d->contextMenuData.linkUrl().toString(QUrl::FullyEncoded);
QString title = d->contextMenuData.linkText().toHtmlEscaped();
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>");
data->setHtml(html);
data->setUrls(QList<QUrl>() << d->contextMenuData.linkUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadLinkToDisk:
if (d->contextMenuData.linkUrl().isValid())
d->adapter->download(d->contextMenuData.linkUrl(), d->contextMenuData.d->suggestedFileName);
break;
case CopyImageToClipboard:
if (d->contextMenuData.d->hasImageContent &&
(d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeImage ||
d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeCanvas))
{
d->adapter->copyImageAt(d->contextMenuData.position());
}
break;
case CopyImageUrlToClipboard:
if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeImage) {
QString urlString = d->contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
QString title = d->contextMenuData.linkText();
if (!title.isEmpty())
title = QStringLiteral(" alt=\"%1\"").arg(title.toHtmlEscaped());
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral("></img>");
data->setHtml(html);
data->setUrls(QList<QUrl>() << d->contextMenuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadImageToDisk:
case DownloadMediaToDisk:
if (d->contextMenuData.mediaUrl().isValid())
d->adapter->download(d->contextMenuData.mediaUrl(), d->contextMenuData.d->suggestedFileName);
break;
case CopyMediaUrlToClipboard:
if (d->contextMenuData.mediaUrl().isValid() &&
(d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
{
QString urlString = d->contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
QMimeData *data = new QMimeData();
data->setText(urlString);
if (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio)
data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"></audio>"));
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
else
data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"></video>"));
data->setUrls(QList<QUrl>() << d->contextMenuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case ToggleMediaControls:
if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) {
bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaControls);
d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerControls, enable);
}
break;
case ToggleMediaLoop:
if (d->contextMenuData.mediaUrl().isValid() &&
(d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
{
bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaLoop);
d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerLoop, enable);
}
break;
case ToggleMediaPlayPause:
if (d->contextMenuData.mediaUrl().isValid() &&
(d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
{
bool enable = (d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaPaused);
d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerPlay, enable);
}
break;
case ToggleMediaMute:
if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaHasAudio) {
bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaMuted);
d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerMute, enable);
}
break;
case InspectElement:
d->adapter->inspectElementAt(d->contextMenuData.position());
break;
case ExitFullScreen:
d->adapter->exitFullScreen();
break;
case RequestClose:
d->adapter->requestClose();
break;
case SavePage:
d->adapter->save();
break;
default:
Q_UNREACHABLE();
}
}
const QQuickWebEngineContextMenuData *QQuickWebEngineViewExperimental::contextMenuData() const
{
Q_D(const QQuickWebEngineView);
return &d->contextMenuData;
}
QSizeF QQuickWebEngineView::contentsSize() const
{
Q_D(const QQuickWebEngineView);
return d->adapter->lastContentsSize();
}
QPointF QQuickWebEngineView::scrollPosition() const
{
Q_D(const QQuickWebEngineView);
return d->adapter->lastScrollOffset();
}
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
void QQuickWebEngineViewPrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script)
{
Q_ASSERT(p && p->data);
QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data);
UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController();
d->m_userScripts.append(script);
// If the adapter hasn't been instantiated, we'll bind the scripts in ensureContentsAdapter()
if (!d->adapter)
return;
script->d_func()->bind(resourceController, d->adapter.data());
}
int QQuickWebEngineViewPrivate::userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p)
{
Q_ASSERT(p && p->data);
QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data);
return d->m_userScripts.count();
}
QQuickWebEngineScript *QQuickWebEngineViewPrivate::userScripts_at(QQmlListProperty<QQuickWebEngineScript> *p, int idx)
{
Q_ASSERT(p && p->data);
QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data);
return d->m_userScripts.at(idx);
}
void QQuickWebEngineViewPrivate::userScripts_clear(QQmlListProperty<QQuickWebEngineScript> *p)
{
Q_ASSERT(p && p->data);
QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data);
UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController();
resourceController->clearAllScripts(d->adapter.data());
d->m_userScripts.clear();
}
void QQuickWebEngineView::componentComplete()
{
QQuickItem::componentComplete();
QTimer::singleShot(0, this, &QQuickWebEngineView::lazyInitialize);
}
void QQuickWebEngineView::lazyInitialize()
{
Q_D(QQuickWebEngineView);
d->ensureContentsAdapter();
}
QQuickWebEngineFullScreenRequest::QQuickWebEngineFullScreenRequest()
: m_viewPrivate(0)
, m_toggleOn(false)
{
}
QQuickWebEngineFullScreenRequest::QQuickWebEngineFullScreenRequest(QQuickWebEngineViewPrivate *viewPrivate, const QUrl &origin, bool toggleOn)
: m_viewPrivate(viewPrivate)
, m_origin(origin)
, m_toggleOn(toggleOn)
{
}
void QQuickWebEngineFullScreenRequest::accept()
{
if (m_viewPrivate)
m_viewPrivate->setFullScreenMode(m_toggleOn);
}
void QQuickWebEngineFullScreenRequest::reject()
{
if (m_viewPrivate)
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793
m_viewPrivate->setFullScreenMode(!m_toggleOn);
}
QQuickWebEngineViewExperimental::QQuickWebEngineViewExperimental(QQuickWebEngineViewPrivate *viewPrivate)
: q_ptr(0)
, d_ptr(viewPrivate)
{
}
QQuickWebEngineViewport *QQuickWebEngineViewExperimental::viewport() const
{
Q_D(const QQuickWebEngineView);
return d->viewport();
}
QQuickWebEngineViewport::QQuickWebEngineViewport(QQuickWebEngineViewPrivate *viewPrivate)
: d_ptr(viewPrivate)
{
}
qreal QQuickWebEngineViewport::devicePixelRatio() const
{
Q_D(const QQuickWebEngineView);
return d->devicePixelRatio;
}
void QQuickWebEngineViewport::setDevicePixelRatio(qreal devicePixelRatio)
{
Q_D(QQuickWebEngineView);
// Valid range is [1, inf)
devicePixelRatio = qMax(qreal(1.0), devicePixelRatio);
if (d->devicePixelRatio == devicePixelRatio)
return;
d->setDevicePixelRatio(devicePixelRatio);
if (!d->adapter)
return;
d->adapter->dpiScaleChanged();
Q_EMIT devicePixelRatioChanged();
}
QT_END_NAMESPACE