diff options
author | Jüri Valdmann <juri.valdmann@qt.io> | 2018-09-20 10:26:37 +0200 |
---|---|---|
committer | Jüri Valdmann <juri.valdmann@qt.io> | 2018-10-29 09:43:04 +0000 |
commit | 36d230c44c7e2f6fccf224b4a0ab5efe77117e0a (patch) | |
tree | 1a782829d2838908a461799bf4b8fd651dad6958 /src/webengine | |
parent | 2a6193b00e1d756e9a7a6032640b413c184ae4f0 (diff) |
Stop showing speculative frames
Chromium creates "speculative" frames (RenderFrameHost and company) for pending
cross-process navigations (and maybe other navigations too). For example, a
redirect from http://qt.io to https://qt.io will trigger this, as described in
the bug report.
These speculative frames are loading in the background and only shown once they
are officially ready (as decided by the RenderFrameHostManager and signaled to
WebContentsObserver::RenderViewHostChanged). At least, this is how it's supposed
to work and how it works in Chrome. In WebEngine, however, we actually show
these speculative frames as soon as they are created and before they are ready.
This runs into the problem that the if the speculative frame is dropped (instead
of committed), then Chromium will not ask us to re-show the old frame (since it
hasn't actually asked to us to show the new frame, it naturally assumes we are
still showing the old one).
Fixes: QTBUG-68727
Change-Id: I9d53035ce60e3a002d5412d4473d940a32644b5d
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/webengine')
6 files changed, 75 insertions, 29 deletions
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index a3a12819b..39901e693 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -669,6 +669,12 @@ void QQuickWebEngineViewPrivate::printRequested() }); } +void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegate *newWidgetBase) +{ + Q_Q(QQuickWebEngineView); + bindViewAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateQuick *>(newWidgetBase)); +} + WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { return m_settings->d_ptr.data(); @@ -846,6 +852,52 @@ void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) } } +void QQuickWebEngineViewPrivate::bindViewAndWidget(QQuickWebEngineView *view, + RenderWidgetHostViewQtDelegateQuick *widget) +{ + auto oldWidget = view ? view->d_func()->widget : nullptr; + auto oldView = widget ? widget->m_view : nullptr; + + // Change pointers first. + + if (widget && oldView != view) { + if (oldView) + oldView->d_func()->widget = nullptr; + widget->m_view = view; + } + + if (view && oldWidget != widget) { + if (oldWidget) + oldWidget->m_view = nullptr; + view->d_func()->widget = widget; + } + + // Then notify. + + if (widget && oldView != view && oldView) + oldView->d_func()->widgetChanged(widget, nullptr); + + if (view && oldWidget != widget) + view->d_func()->widgetChanged(oldWidget, widget); +} + +void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegateQuick *oldWidget, + RenderWidgetHostViewQtDelegateQuick *newWidget) +{ + Q_Q(QQuickWebEngineView); + + if (oldWidget) + oldWidget->setParentItem(nullptr); + + if (newWidget) { + newWidget->setParentItem(q); + newWidget->setSize(q->boundingRect().size()); + // Focus on creation if the view accepts it + if (q->activeFocusOnPress()) + newWidget->setFocus(true); + } +} + void QQuickWebEngineViewPrivate::updateAction(QQuickWebEngineView::WebAction action) const { QQuickWebEngineAction *a = actions[action]; @@ -1494,11 +1546,9 @@ void QQuickWebEngineView::fullScreenCancelled() void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickItem::geometryChanged(newGeometry, oldGeometry); - const QList<QQuickItem *> children = childItems(); - for (QQuickItem *child : children) { - if (qobject_cast<RenderWidgetHostViewQtDelegateQuick *>(child)) - child->setSize(newGeometry.size()); - } + Q_D(QQuickWebEngineView); + if (d->widget) + d->widget->setSize(newGeometry.size()); } void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value) diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index d20bfca46..cbba9b568 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -63,8 +63,9 @@ #include <QtGui/qaccessibleobject.h> namespace QtWebEngineCore { -class WebContentsAdapter; +class RenderWidgetHostViewQtDelegateQuick; class UIDelegatesManager; +class WebContentsAdapter; } QT_BEGIN_NAMESPACE @@ -157,6 +158,7 @@ public: QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; void printRequested() override; + void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidgetBase) override; void updateAction(QQuickWebEngineView::WebAction) const; void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); @@ -165,6 +167,10 @@ public: void ensureContentsAdapter(); void setFullScreenMode(bool); + static void bindViewAndWidget(QQuickWebEngineView *view, QtWebEngineCore::RenderWidgetHostViewQtDelegateQuick *widget); + void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegateQuick *oldWidget, + QtWebEngineCore::RenderWidgetHostViewQtDelegateQuick *newWidget); + // QQmlListPropertyHelpers static void userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script); static int userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p); @@ -198,6 +204,7 @@ public: uint m_webChannelWorld; bool m_isBeingAdopted; mutable QQuickWebEngineAction *actions[QQuickWebEngineView::WebActionCount]; + QtWebEngineCore::RenderWidgetHostViewQtDelegateQuick *widget = nullptr; bool profileInitialized() const; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index baece82f3..d23e64774 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -55,7 +55,6 @@ RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderW : m_client(client) , m_isPopup(isPopup) , m_isPasswordInput(false) - , m_initialized(false) { setFlag(ItemHasContents); setAcceptedMouseButtons(Qt::AllButtons); @@ -85,16 +84,9 @@ RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderW } -void RenderWidgetHostViewQtDelegateQuick::initAsChild(WebContentsAdapterClient* container) +RenderWidgetHostViewQtDelegateQuick::~RenderWidgetHostViewQtDelegateQuick() { - QQuickWebEngineView *view = static_cast<QQuickWebEngineViewPrivate *>(container)->q_func(); - setParentItem(view); - setSize(view->boundingRect().size()); - // Focus on creation if the view accepts it - if (view->activeFocusOnPress()) - setFocus(true); - m_initialized = true; - + QQuickWebEngineViewPrivate::bindViewAndWidget(nullptr, this); } void RenderWidgetHostViewQtDelegateQuick::initAsPopup(const QRect &r) @@ -106,7 +98,6 @@ void RenderWidgetHostViewQtDelegateQuick::initAsPopup(const QRect &r) setWidth(rect.width()); setHeight(rect.height()); setVisible(true); - m_initialized = true; } QRectF RenderWidgetHostViewQtDelegateQuick::screenRect() const @@ -361,8 +352,7 @@ void RenderWidgetHostViewQtDelegateQuick::itemChange(ItemChange change, const It m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent *)), SLOT(onHide()))); } - if (m_initialized) - m_client->windowChanged(); + m_client->windowChanged(); } else if (change == QQuickItem::ItemVisibleHasChanged) { if (!m_isPopup && !value.boolValue) onHide(); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h index 74cddf476..6b855c824 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h @@ -44,6 +44,11 @@ #include <QQuickItem> +QT_BEGIN_NAMESPACE +class QQuickWebEngineView; +class QQuickWebEngineViewPrivate; +QT_END_NAMESPACE + namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegateQuick : public QQuickItem, public RenderWidgetHostViewQtDelegate @@ -51,8 +56,8 @@ class RenderWidgetHostViewQtDelegateQuick : public QQuickItem, public RenderWidg Q_OBJECT public: RenderWidgetHostViewQtDelegateQuick(RenderWidgetHostViewQtDelegateClient *client, bool isPopup); + ~RenderWidgetHostViewQtDelegateQuick(); - void initAsChild(WebContentsAdapterClient* container) override; void initAsPopup(const QRect&) override; QRectF screenRect() const override; QRectF contentsRect() const override; @@ -102,12 +107,14 @@ private slots: void onHide(); private: + friend QQuickWebEngineViewPrivate; + RenderWidgetHostViewQtDelegateClient *m_client; QList<QMetaObject::Connection> m_windowConnections; bool m_isPopup; bool m_isPasswordInput; - bool m_initialized; QPoint m_lastGlobalPos; + QQuickWebEngineView *m_view = nullptr; }; } // namespace QtWebEngineCore diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp index dd37ff6fa..d3c88148e 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -54,13 +54,6 @@ RenderWidgetHostViewQtDelegateQuickWindow::~RenderWidgetHostViewQtDelegateQuickW { } -void RenderWidgetHostViewQtDelegateQuickWindow::initAsChild(WebContentsAdapterClient *container) -{ - Q_UNUSED(container); - // We should only use this wrapper class for webUI popups. - Q_UNREACHABLE(); -} - void RenderWidgetHostViewQtDelegateQuickWindow::initAsPopup(const QRect &screenRect) { m_realDelegate->initAsPopup(QRect(QPoint(0, 0), screenRect.size())); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h index 6a1be8b7f..df241bf3a 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h @@ -55,7 +55,6 @@ public: RenderWidgetHostViewQtDelegateQuickWindow(RenderWidgetHostViewQtDelegate *realDelegate); ~RenderWidgetHostViewQtDelegateQuickWindow(); - void initAsChild(WebContentsAdapterClient* container) override; void initAsPopup(const QRect&) override; QRectF screenRect() const override; QRectF contentsRect() const override; |