diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 26ea4f4ae81b215933470d63530a9cfd5ecefcc6..bf0e80be9a1b6949eab17864db4009ad75d6dca7 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -628,6 +628,7 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&)
 
 void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame)
 {
+    bool scrollOffsetChanged = (m_lastScrollOffset != frame->metadata.root_scroll_offset);
     m_lastScrollOffset = frame->metadata.root_scroll_offset;
     Q_ASSERT(!m_needsDelegatedFrameAck);
     m_needsDelegatedFrameAck = true;
@@ -648,6 +649,9 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, sco
         m_adapterClient->loadVisuallyCommitted();
         m_didFirstVisuallyNonEmptyLayout = false;
     }
+
+    if (scrollOffsetChanged)
+        m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset));
 }
 
 void RenderWidgetHostViewQt::GetScreenInfo(blink::WebScreenInfo* results)
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index 9e54618889d17beade8788fa21eca3529048365d..0cefeb07a6076045e31ba01bf66f72c1d7ad67bf 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -94,6 +94,11 @@ inline QPoint toQt(const gfx::Point &point)
     return QPoint(point.x(), point.y());
 }
 
+inline QPointF toQt(const gfx::Vector2dF &point)
+{
+    return QPointF(point.x(), point.y());
+}
+
 inline gfx::Point toGfx(const QPoint& point)
 {
   return gfx::Point(point.x(), point.y());
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 2b2512fc3b51dab7943f5f723b18fca4cafa1af6..8f69fb92c5999113cb2a33abb866f4e76a5eeafa 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -829,6 +829,14 @@ void WebContentsAdapter::wasHidden()
     d->webContents->WasHidden();
 }
 
+QPointF WebContentsAdapter::lastScrollOffset() const
+{
+    Q_D(const WebContentsAdapter);
+    if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView())
+        return toQt(rwhv->GetLastScrollOffset());
+    return QPointF();
+}
+
 void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags)
 {
     Q_D(WebContentsAdapter);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index ecb084e56efeddda0abeff66f622aca00759a630..39cc48834357828dd7d1b2a8120c9afa5dd5661e 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -143,6 +143,8 @@ public:
     QWebChannel *webChannel() const;
     void setWebChannel(QWebChannel *);
 
+    QPointF lastScrollOffset() const;
+
     // meant to be used within WebEngineCore only
     content::WebContents *webContents() const;
 
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 3ae84f9c8773a9207060f0b00f87bb64e924b470..94c6835ed3b132498ddc637d6e0603dc0cc961c0 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -236,6 +236,7 @@ public:
     virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0;
 
     virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) = 0;
+    virtual void updateScrollPosition(const QPointF &position) = 0;
 
     virtual BrowserContextAdapter* browserContextAdapter() = 0;
 
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index b22b2798eb32c10ab475860a49380bcf37f6789e..1a8a19993df69e6ed6fc29fdfa56ceba16b582fa 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -893,6 +893,12 @@ 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::renderProcessTerminated(
         RenderProcessTerminationStatus terminationStatus, int exitCode)
 {
@@ -1302,6 +1308,12 @@ void QQuickWebEngineView::triggerWebAction(WebAction action)
     }
 }
 
+QPointF QQuickWebEngineView::scrollPosition() const
+{
+    Q_D(const QQuickWebEngineView);
+    return d->adapter->lastScrollOffset();
+}
+
 void QQuickWebEngineViewPrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script)
 {
     Q_ASSERT(p && p->data);
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 22cca3277ac090fafc9d72a929853718b68b19f7..aaf4c4bcf197e8649f1d6aef1b00e9a06e4f811b 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -104,6 +104,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
     Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 1)
     Q_PROPERTY(bool activeFocusOnPress READ activeFocusOnPress WRITE setActiveFocusOnPress NOTIFY activeFocusOnPressChanged REVISION 2)
     Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged REVISION 2)
+    Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged FINAL REVISION 3)
 
 #ifdef ENABLE_QML_TESTSUPPORT_API
     Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport FINAL)
@@ -137,6 +138,7 @@ public:
     void setZoomFactor(qreal arg);
     QColor backgroundColor() const;
     void setBackgroundColor(const QColor &color);
+    QPointF scrollPosition() const;
 
     QQuickWebEngineViewExperimental *experimental() const;
 
@@ -305,6 +307,7 @@ Q_SIGNALS:
     Q_REVISION(2) void activeFocusOnPressChanged(bool);
     Q_REVISION(2) void backgroundColorChanged();
     Q_REVISION(2) void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode);
+    Q_REVISION(3) void scrollPositionChanged(const QPointF& position);
 
 protected:
     void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 0140111b924a60bfa01bc4adc14114787ed23ede..3e6aa6317ef47efba13f466740cd19a97b78dc14 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -169,6 +169,7 @@ public:
     virtual void moveValidationMessage(const QRect &anchor) Q_DECL_OVERRIDE;
     virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus,
                                      int exitCode) Q_DECL_OVERRIDE;
+    virtual void updateScrollPosition(const QPointF &position) Q_DECL_OVERRIDE;
 
     virtual QtWebEngineCore::BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE;
 
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 677f67cbe97fbd61528774311fd59eaff66b5e31..434667e4951e9c55d811d5cadfcad3dfd7e5758c 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -367,6 +367,12 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input)
     }
 }
 
+void QWebEnginePagePrivate::updateScrollPosition(const QPointF &position)
+{
+    Q_Q(QWebEnginePage);
+    Q_EMIT q->scrollPositionChanged(position);
+}
+
 BrowserContextAdapter *QWebEnginePagePrivate::browserContextAdapter()
 {
     return profile->d_ptr->browserContext();
@@ -1290,6 +1296,17 @@ bool QWebEnginePage::isFullScreen()
     return d->view ? d->view->isFullScreen() : false;
 }
 
+/*!
+    \since 5.7
+
+    Returns the scroll position of the page contents.
+*/
+QPointF QWebEnginePage::scrollPosition() const
+{
+    Q_D(const QWebEnginePage);
+    return d->adapter->lastScrollOffset();
+}
+
 QT_END_NAMESPACE
 
 #include "moc_qwebenginepage.cpp"
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 90fa62f97d57b50e7a43ab8e157c482e08756e1c..13d6b49352a8fe7f2dd8e73412c457eec53978d0 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -69,6 +69,7 @@ class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject {
     Q_PROPERTY(QUrl url READ url WRITE setUrl)
     Q_PROPERTY(QUrl iconUrl READ iconUrl)
     Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
+    Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged)
 
 public:
     enum WebAction {
@@ -224,6 +225,8 @@ public:
     qreal zoomFactor() const;
     void setZoomFactor(qreal factor);
 
+    QPointF scrollPosition() const;
+
     void runJavaScript(const QString& scriptSource);
 #ifdef Q_QDOC
     void runJavaScript(const QString& scriptSource, FunctorOrLambda resultCallback);
@@ -263,6 +266,8 @@ Q_SIGNALS:
     // Was iconChanged() in QWebFrame
     void iconUrlChanged(const QUrl &url);
 
+    void scrollPositionChanged(const QPointF &position);
+
 protected:
     virtual QWebEnginePage *createWindow(WebWindowType type);
     virtual QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes);
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 8d9bc25177a06e04729bbc8db93d48e527c25467..e67e6303edeef162a848fb65d081255de724e075 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -121,6 +121,7 @@ public:
     virtual void moveValidationMessage(const QRect &anchor) Q_DECL_OVERRIDE;
     virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus,
                                      int exitCode) Q_DECL_OVERRIDE;
+    virtual void updateScrollPosition(const QPointF &position);
 
     virtual QtWebEngineCore::BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE;