diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 187565a7618ed1a15cb80bdee054bbeb8e8fd7e7..fbb7c1f9edd74c0ad10275d680cb844907aa4df8 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -902,7 +902,7 @@ QWebEnginePage::~QWebEnginePage()
     Q_D(QWebEnginePage);
     setDevToolsPage(nullptr);
     d->adapter->stopFinding();
-    QWebEngineViewPrivate::bind(nullptr, this, true);
+    QWebEngineViewPrivate::removePageFromView(this);
 }
 
 QWebEngineHistory *QWebEnginePage::history() const
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index aa51e5b0ef4c9c1e34945b2ad68974034d5e754e..e6f9fcb49c7f7986ecccd02efec1e9ca7628ccf7 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -55,33 +55,77 @@
 
 QT_BEGIN_NAMESPACE
 
-void QWebEngineViewPrivate::bind(QWebEngineView *view, QWebEnginePage *page, bool pageBeingDeleted)
+void QWebEngineViewPrivate::notify(QWebEngineView *view, QWebEnginePage *oldPage, QWebEnginePage *newPage)
+{
+    Q_ASSERT(view);
+
+    auto oldUrl = oldPage ? oldPage->url() : QUrl();
+    auto newUrl = newPage ? newPage->url() : QUrl();
+    if (oldUrl != newUrl)
+        Q_EMIT view->urlChanged(newUrl);
+
+    auto oldTitle = oldPage ? oldPage->title() : QString();
+    auto newTitle = newPage ? newPage->title() : QString();
+    if (oldTitle != newTitle)
+        Q_EMIT view->titleChanged(newTitle);
+
+    auto oldIcon = oldPage ? oldPage->iconUrl() : QUrl();
+    auto newIcon = newPage ? newPage->iconUrl() : QUrl();
+    if (oldIcon != newIcon) {
+        Q_EMIT view->iconUrlChanged(newIcon);
+        Q_EMIT view->iconChanged(newPage ? newPage->icon() : QIcon());
+    }
+
+    if ((oldPage && oldPage->hasSelection()) || (newPage && newPage->hasSelection()))
+        Q_EMIT view->selectionChanged();
+}
+
+QWebEnginePage* QWebEngineViewPrivate::removeViewFromPage(QWebEngineView *view)
+{
+    Q_ASSERT(view);
+    QWebEnginePage *oldPage = view->d_func()->page;
+
+    if (oldPage) {
+        oldPage->disconnect(view);
+        oldPage->d_func()->view = nullptr;
+        if (oldPage->parent() != view)
+            oldPage->d_func()->adapter->reattachRWHV();
+    }
+    return oldPage;
+}
+
+void QWebEngineViewPrivate::removePageFromView(QWebEnginePage *page)
+{
+    Q_ASSERT(page);
+    if (QWebEngineView *oldView = page->d_func()->view) {
+        page->disconnect(oldView);
+        page->d_func()->view = nullptr;
+        oldView->d_func()->page = nullptr;
+        notify(oldView, page, nullptr);
+    }
+}
+
+void QWebEngineViewPrivate::bind(QWebEngineView *view, QWebEnginePage *page)
 {
     if (view && page == view->d_func()->page)
         return;
 
     if (page) {
         // Un-bind page from its current view.
-        if (QWebEngineView *oldView = page->d_func()->view) {
-            page->disconnect(oldView);
-            oldView->d_func()->page = nullptr;
-        }
+        removePageFromView(page);
         page->d_func()->view = view;
-        if (!pageBeingDeleted)
-            page->d_func()->adapter->reattachRWHV();
+        page->d_func()->adapter->reattachRWHV();
     }
 
     if (view) {
         // Un-bind view from its current page.
-        if (QWebEnginePage *oldPage = view->d_func()->page) {
-            oldPage->disconnect(view);
-            oldPage->d_func()->view = nullptr;
-            if (oldPage->parent() == view)
-                delete oldPage;
-            else
-                oldPage->d_func()->adapter->reattachRWHV();
-        }
+        QWebEnginePage *oldPage = removeViewFromPage(view);
+
         view->d_func()->page = page;
+        notify(view, oldPage, page);
+
+        if (oldPage && oldPage->parent() == view)
+            delete oldPage;
     }
 
     if (view && page) {
@@ -149,7 +193,7 @@ QWebEngineView::QWebEngineView(QWidget *parent)
 
 QWebEngineView::~QWebEngineView()
 {
-    QWebEngineViewPrivate::bind(this, nullptr);
+    QWebEngineViewPrivate::removeViewFromPage(this);
 }
 
 QWebEnginePage* QWebEngineView::page() const
diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h
index bfb44bec5b29c05cea7702aba08e6f0378e81e16..1845bfb603d3e35977fc8b687a4e6242db977c23 100644
--- a/src/webenginewidgets/api/qwebengineview_p.h
+++ b/src/webenginewidgets/api/qwebengineview_p.h
@@ -65,7 +65,10 @@ public:
     Q_DECLARE_PUBLIC(QWebEngineView)
     QWebEngineView *q_ptr;
 
-    static void bind(QWebEngineView *view, QWebEnginePage *page, bool pageBeingDeleted = false);
+    static void notify(QWebEngineView *view, QWebEnginePage *oldPage, QWebEnginePage *newPage);
+    static QWebEnginePage* removeViewFromPage(QWebEngineView *view);
+    static void removePageFromView(QWebEnginePage *page);
+    static void bind(QWebEngineView *view, QWebEnginePage *page);
 
     QWebEngineViewPrivate();
 
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 57f5f6def5acb1f26b3c5946c8313ff1d50ad97d..78677e459157f03939b4ea8d1ef95eb58e2495db 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -134,6 +134,8 @@ private Q_SLOTS:
     void renderHints();
     void getWebKitVersion();
 
+    void changePage_data();
+    void changePage();
     void reusePage_data();
     void reusePage();
     void microFocusCoordinates();
@@ -260,6 +262,100 @@ void tst_QWebEngineView::getWebKitVersion()
 #endif
 }
 
+void tst_QWebEngineView::changePage_data()
+{
+    QString html = "<html><head><title>%1</title>"
+                   "<link rel='icon' href='file://" TESTS_SOURCE_DIR "/resources/image2.png'></head></html>";
+    QUrl urlFrom("data:text/html," + html.arg("TitleFrom"));
+    QUrl urlTo("data:text/html," + html.arg("TitleTo"));
+    QUrl nullPage("data:text/html,<html/>");
+    QTest::addColumn<QUrl>("urlFrom");
+    QTest::addColumn<QUrl>("urlTo");
+    QTest::addColumn<bool>("fromIsNullPage");
+    QTest::addColumn<bool>("toIsNullPage");
+    QTest::newRow("From empty page to url") << nullPage << urlTo << true << false;
+    QTest::newRow("From url to empty content page") << urlFrom << nullPage << false << true;
+    QTest::newRow("From one content to another") << urlFrom << urlTo << false << false;
+}
+
+void tst_QWebEngineView::changePage()
+{
+    QScopedPointer<QWebEngineView> view(new QWebEngineView); view->resize(640, 480); view->show();
+
+    QFETCH(QUrl, urlFrom);
+    QFETCH(QUrl, urlTo);
+    QFETCH(bool, fromIsNullPage);
+    QFETCH(bool, toIsNullPage);
+
+    QSignalSpy spyUrl(view.get(), &QWebEngineView::urlChanged);
+    QSignalSpy spyTitle(view.get(), &QWebEngineView::titleChanged);
+    QSignalSpy spyIconUrl(view.get(), &QWebEngineView::iconUrlChanged);
+    QSignalSpy spyIcon(view.get(), &QWebEngineView::iconChanged);
+
+    QScopedPointer<QWebEnginePage> pageFrom(new QWebEnginePage);
+    QSignalSpy pageFromLoadSpy(pageFrom.get(), &QWebEnginePage::loadFinished);
+    QSignalSpy pageFromIconLoadSpy(pageFrom.get(), &QWebEnginePage::iconChanged);
+    pageFrom->load(urlFrom);
+    QTRY_COMPARE(pageFromLoadSpy.count(), 1);
+    QCOMPARE(pageFromLoadSpy.last().value(0).toBool(), true);
+    if (!fromIsNullPage) {
+        QTRY_COMPARE(pageFromIconLoadSpy.count(), 1);
+        QVERIFY(!pageFromIconLoadSpy.last().value(0).isNull());
+    }
+
+    view->setPage(pageFrom.get());
+
+    QTRY_COMPARE(spyUrl.count(), 1);
+    QCOMPARE(spyUrl.last().value(0).toUrl(), pageFrom->url());
+    QTRY_COMPARE(spyTitle.count(), 1);
+    QCOMPARE(spyTitle.last().value(0).toString(), pageFrom->title());
+
+    QTRY_COMPARE(spyIconUrl.count(), fromIsNullPage ? 0 : 1);
+    QTRY_COMPARE(spyIcon.count(), fromIsNullPage ? 0 : 1);
+    if (!fromIsNullPage) {
+        QVERIFY(!pageFrom->iconUrl().isEmpty());
+        QCOMPARE(spyIconUrl.last().value(0).toUrl(), pageFrom->iconUrl());
+        QCOMPARE(spyIcon.last().value(0), QVariant::fromValue(pageFrom->icon()));
+    }
+
+    QScopedPointer<QWebEnginePage> pageTo(new QWebEnginePage);
+    QSignalSpy pageToLoadSpy(pageTo.get(), &QWebEnginePage::loadFinished);
+    QSignalSpy pageToIconLoadSpy(pageTo.get(), &QWebEnginePage::iconChanged);
+    pageTo->load(urlTo);
+    QTRY_COMPARE(pageToLoadSpy.count(), 1);
+    QCOMPARE(pageToLoadSpy.last().value(0).toBool(), true);
+    if (!toIsNullPage) {
+        QTRY_COMPARE(pageToIconLoadSpy.count(), 1);
+        QVERIFY(!pageToIconLoadSpy.last().value(0).isNull());
+    }
+
+    view->setPage(pageTo.get());
+
+    QTRY_COMPARE(spyUrl.count(), 2);
+    QCOMPARE(spyUrl.last().value(0).toUrl(), pageTo->url());
+    QTRY_COMPARE(spyTitle.count(), 2);
+    QCOMPARE(spyTitle.last().value(0).toString(), pageTo->title());
+
+    bool iconIsSame = fromIsNullPage == toIsNullPage;
+    int iconChangeNotifyCount = fromIsNullPage ? (iconIsSame ? 0 : 1) : (iconIsSame ? 1 : 2);
+
+    QTRY_COMPARE(spyIconUrl.count(), iconChangeNotifyCount);
+    QTRY_COMPARE(spyIcon.count(), iconChangeNotifyCount);
+    QCOMPARE(pageFrom->iconUrl() == pageTo->iconUrl(), iconIsSame);
+    if (!iconIsSame) {
+        QCOMPARE(spyIconUrl.last().value(0).toUrl(), pageTo->iconUrl());
+        QCOMPARE(spyIcon.last().value(0), QVariant::fromValue(pageTo->icon()));
+    }
+
+    // verify no emits on destroy with the same number of signals in spy
+    view.reset();
+    qApp->processEvents();
+    QTRY_COMPARE(spyUrl.count(), 2);
+    QTRY_COMPARE(spyTitle.count(), 2);
+    QTRY_COMPARE(spyIconUrl.count(), iconChangeNotifyCount);
+    QTRY_COMPARE(spyIcon.count(), iconChangeNotifyCount);
+}
+
 void tst_QWebEngineView::reusePage_data()
 {
     QTest::addColumn<QString>("html");