diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index 4d7513fae98c612056bc96eae244f7a4f33460c7..123a7cc8d712e2a76d67cf4ea5f34b7b75283c57 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -118,10 +118,7 @@ ApplicationWindow {
     Action {
         shortcut: StandardKey.Close
         onTriggered: {
-            if (tabs.count == 1)
-                browserWindow.close()
-            else
-                tabs.removeTab(tabs.currentIndex)
+            currentWebView.triggerWebAction(WebEngineView.RequestClose);
         }
     }
     Action {
@@ -415,6 +412,13 @@ ApplicationWindow {
                     reloadTimer.running = true
                 }
 
+                onWindowCloseRequested: {
+                    if (tabs.count == 1)
+                        browserWindow.close()
+                    else
+                        tabs.removeTab(tabs.currentIndex)
+                }
+
                 Timer {
                     id: reloadTimer
                     interval: 0
diff --git a/examples/webenginewidgets/demobrowser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp
index 9210e3147b69fc75805d59bb86662330eef53e38..9e08426f1f4c5b4d7e06c4cf4839c8d0bdcafa60 100644
--- a/examples/webenginewidgets/demobrowser/tabwidget.cpp
+++ b/examples/webenginewidgets/demobrowser/tabwidget.cpp
@@ -223,7 +223,7 @@ TabWidget::TabWidget(QWidget *parent)
     setElideMode(Qt::ElideRight);
 
     connect(m_tabBar, SIGNAL(newTab()), this, SLOT(newTab()));
-    connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int)));
+    connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(requestCloseTab(int)));
     connect(m_tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int)));
     connect(m_tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int)));
     connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int)));
@@ -241,7 +241,7 @@ TabWidget::TabWidget(QWidget *parent)
     m_closeTabAction = new QAction(QIcon(QLatin1String(":closetab.png")), tr("&Close Tab"), this);
     m_closeTabAction->setShortcuts(QKeySequence::Close);
     m_closeTabAction->setIconVisibleInMenu(false);
-    connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(closeTab()));
+    connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(requestCloseTab()));
 
     m_nextTabAction = new QAction(tr("Show Next Tab"), this);
     QList<QKeySequence> shortcuts;
@@ -552,12 +552,8 @@ void TabWidget::windowCloseRequested()
     WebPage *webPage = qobject_cast<WebPage*>(sender());
     WebView *webView = qobject_cast<WebView*>(webPage->view());
     int index = webViewIndex(webView);
-    if (index >= 0) {
-        if (count() == 1)
-            webView->webPage()->mainWindow()->close();
-        else
-            closeTab(index);
-    }
+    if (index >= 0)
+        closeTab(index);
 }
 
 void TabWidget::closeOtherTabs(int index)
@@ -582,12 +578,22 @@ void TabWidget::cloneTab(int index)
 }
 
 // When index is -1 index chooses the current tab
-void TabWidget::closeTab(int index)
+void TabWidget::requestCloseTab(int index)
 {
     if (index < 0)
         index = currentIndex();
     if (index < 0 || index >= count())
         return;
+    WebView *tab = webView(index);
+    if (!tab)
+        return;
+    tab->page()->triggerAction(QWebEnginePage::RequestClose);
+}
+
+void TabWidget::closeTab(int index)
+{
+    if (index < 0 || index >= count())
+        return;
 
     bool hasFocus = false;
     if (WebView *tab = webView(index)) {
diff --git a/examples/webenginewidgets/demobrowser/tabwidget.h b/examples/webenginewidgets/demobrowser/tabwidget.h
index f6c4edba264540a4fc67ec0bbcc2f01bc96ea820..0f2a20c34d5463370cd846b3e92ff4d465ccbae6 100644
--- a/examples/webenginewidgets/demobrowser/tabwidget.h
+++ b/examples/webenginewidgets/demobrowser/tabwidget.h
@@ -196,7 +196,8 @@ public slots:
     void loadUrlInCurrentTab(const QUrl &url);
     WebView *newTab(bool makeCurrent = true);
     void cloneTab(int index = -1);
-    void closeTab(int index = -1);
+    void requestCloseTab(int index = -1);
+    void closeTab(int index);
     void closeOtherTabs(int index);
     void reloadTab(int index = -1);
     void reloadAllTabs();
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 2b2512fc3b51dab7943f5f723b18fca4cafa1af6..92c831f94516b7b39697c1b32eb07e8fdbef6cfb 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -576,6 +576,12 @@ void WebContentsAdapter::selectAll()
     d->webContents->SelectAll();
 }
 
+void WebContentsAdapter::requestClose()
+{
+    Q_D(WebContentsAdapter);
+    d->webContents->DispatchBeforeUnload(false);
+}
+
 void WebContentsAdapter::navigateToIndex(int offset)
 {
     Q_D(WebContentsAdapter);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index ecb084e56efeddda0abeff66f622aca00759a630..54bec9adf21fef7281bebb113d7cfee1768f92d8 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -128,6 +128,7 @@ public:
     void inspectElementAt(const QPoint &location);
     bool hasInspector() const;
     void exitFullScreen();
+    void requestClose();
 
     void wasShown();
     void wasHidden();
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 2b9b6222987fe46422d63e74ab8c63cf0aca2db1..6b203fc904fc2f8b12318e5793f4e3e4e40b415a 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -208,6 +208,7 @@ public:
     virtual void unhandledKeyEvent(QKeyEvent *event) = 0;
     virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect & initialGeometry) = 0;
     virtual void close() = 0;
+    virtual void windowCloseRejected() = 0;
     virtual bool contextMenuRequested(const WebEngineContextMenuData&) = 0;
     virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) = 0;
     virtual void requestFullScreen(bool) = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 1c37f62dfab65638021643729ddc6f61dccc80ff..497910a9c73efb96e27e7fe08f638f00139a837b 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -390,4 +390,13 @@ void WebContentsDelegateQt::MoveValidationMessage(content::WebContents *web_cont
     m_viewClient->moveValidationMessage(toQt(anchor_in_root_view));
 }
 
+void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool proceed, bool *proceed_to_fire_unload)
+{
+    Q_UNUSED(tab);
+    Q_ASSERT(proceed_to_fire_unload);
+    *proceed_to_fire_unload = proceed;
+    if (!proceed)
+        m_viewClient->windowCloseRejected();
+}
+
 } // namespace QtWebEngineCore
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 14421d060eaf39255a04ac3d5c55a3bee2b475aa..abdf75fe55d5bc24c4a590951d1babd844da238e 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -91,6 +91,7 @@ public:
     virtual void ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) Q_DECL_OVERRIDE;
     virtual void HideValidationMessage(content::WebContents *web_contents) Q_DECL_OVERRIDE;
     virtual void MoveValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view) Q_DECL_OVERRIDE;
+    void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) Q_DECL_OVERRIDE;
 
     // WebContentsObserver overrides
     virtual void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) Q_DECL_OVERRIDE;
diff --git a/src/webengine/api/qquickwebenginetestsupport_p.h b/src/webengine/api/qquickwebenginetestsupport_p.h
index 9690e538d0be9d704886a6a74f6d12b4132d73da..d4b50ac2db0a199b4a1ad2a5428f2dd2b1696d4a 100644
--- a/src/webengine/api/qquickwebenginetestsupport_p.h
+++ b/src/webengine/api/qquickwebenginetestsupport_p.h
@@ -80,6 +80,7 @@ public:
 
 Q_SIGNALS:
     void validationMessageShown(const QString &mainText, const QString &subText);
+    void windowCloseRejected();
 
 private:
     QScopedPointer<QQuickWebEngineErrorPage> m_errorPage;
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 96a80a940f30322f3d06df616321589c81cc536a..3a05477a13e2a33fafe1dfb4de2d08d03f6ccfb3 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -508,6 +508,14 @@ void QQuickWebEngineViewPrivate::close()
     emit q->windowCloseRequested();
 }
 
+void QQuickWebEngineViewPrivate::windowCloseRejected()
+{
+#ifdef ENABLE_QML_TESTSUPPORT_API
+    if (m_testSupport)
+        Q_EMIT m_testSupport->windowCloseRejected();
+#endif
+}
+
 void QQuickWebEngineViewPrivate::requestFullScreen(bool fullScreen)
 {
     Q_Q(QQuickWebEngineView);
@@ -1298,6 +1306,9 @@ void QQuickWebEngineView::triggerWebAction(WebAction action)
     case ExitFullScreen:
         d->adapter->exitFullScreen();
         break;
+    case RequestClose:
+        d->adapter->requestClose();
+        break;
     default:
         Q_UNREACHABLE();
     }
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 6efb2b6f9fd5ca43a6a053a6b13384caa0f4c7bc..d1d8dacbbb351d3aa99068ec1e01029aa8060671 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -226,6 +226,7 @@ public:
 
         InspectElement,
         ExitFullScreen,
+        RequestClose,
 
         WebActionCount
     };
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 0140111b924a60bfa01bc4adc14114787ed23ede..271ab63beb99636d39fe55dc8f3054a1d9a8f299 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -143,6 +143,7 @@ public:
     virtual void unhandledKeyEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
     virtual void adoptNewWindow(QtWebEngineCore::WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &) Q_DECL_OVERRIDE;
     virtual void close() Q_DECL_OVERRIDE;
+    virtual void windowCloseRejected() Q_DECL_OVERRIDE;
     virtual void requestFullScreen(bool) Q_DECL_OVERRIDE;
     virtual bool isFullScreen() const Q_DECL_OVERRIDE;
     virtual bool contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &) Q_DECL_OVERRIDE;
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 5d91b3b7fa872cc843e2e839e141452d95b1540e..bb0917918c0570e53129569223947bc6bec3972c 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -224,6 +224,11 @@ void QWebEnginePagePrivate::close()
     Q_EMIT q->windowCloseRequested();
 }
 
+void QWebEnginePagePrivate::windowCloseRejected()
+{
+    // Do nothing for now.
+}
+
 void QWebEnginePagePrivate::didRunJavaScript(quint64 requestId, const QVariant& result)
 {
     m_callbacks.invoke(requestId, result);
@@ -639,6 +644,9 @@ QAction *QWebEnginePage::action(WebAction action) const
     case ExitFullScreen:
         text = tr("Exit Full Screen Mode");
         break;
+    case RequestClose:
+        text = tr("Close Page");
+        break;
     default:
         break;
     }
@@ -809,6 +817,9 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
     case ExitFullScreen:
         d->adapter->exitFullScreen();
         break;
+    case RequestClose:
+        d->adapter->requestClose();
+        break;
     default:
         Q_UNREACHABLE();
     }
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 90fa62f97d57b50e7a43ab8e157c482e08756e1c..4b5e6456d1b7454583a8838e862166fe05739f77 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -108,6 +108,7 @@ public:
 
         InspectElement,
         ExitFullScreen,
+        RequestClose,
 
         WebActionCount
     };
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 8d9bc25177a06e04729bbc8db93d48e527c25467..f5c01ce1b38109c9288ee174b016dc66bad68566 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -95,6 +95,7 @@ public:
     virtual void unhandledKeyEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
     virtual void adoptNewWindow(QtWebEngineCore::WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &initialGeometry) Q_DECL_OVERRIDE;
     virtual void close() Q_DECL_OVERRIDE;
+    virtual void windowCloseRejected() Q_DECL_OVERRIDE;
     virtual bool contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &data) Q_DECL_OVERRIDE;
     virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE;
     virtual void requestFullScreen(bool) Q_DECL_OVERRIDE;
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 4a7545c140c2c6ace307bce9c342f927fb48c4da..b7b3bf0222955276b6828c15f8fee7ae1efcf9c6 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -119,6 +119,9 @@
     \value InspectElement Trigger any attached Web Inspector to inspect the highlighed element.
            (Added in Qt 5.6)
     \value ExitFullScreen Exit the fullscreen mode. (Added in Qt 5.6)
+    \value RequestClose Request to close the web page. If defined, the \c{window.onbeforeunload}
+           handler is run, and the user can confirm or reject to close the page. If the close
+           request is confirmed, \c windowCloseRequested is emitted. (Added in Qt 5.6)
 
     \omitvalue WebActionCount
 
@@ -482,6 +485,8 @@
 
     This signal is emitted whenever the page requests the web browser window to be closed,
     for example through the JavaScript \c{window.close()} call.
+
+    \sa QWebEnginePage::RequestClose
 */
 
 /*!
diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
index 8a01dfa0967d5e8519e2db338d03d750fa955877..e2c5c90096a1c057b541030fde74f6122aaf9ba1 100644
--- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml
+++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
@@ -47,6 +47,7 @@ import QtWebEngine.experimental 1.0
 WebEngineView {
     property var loadStatus: null
     property var viewportReady: false
+    property bool windowCloseRequestedSignalEmitted: false
 
     function waitForLoadSucceeded() {
         var success = _waitFor(function() { return loadStatus == WebEngineView.LoadSucceededStatus })
@@ -69,6 +70,9 @@ WebEngineView {
         loadStatus = null
         return stop
     }
+    function waitForWindowCloseRequested() {
+        return _waitFor(function() { return windowCloseRequestedSignalEmitted; });
+    }
     function _waitFor(predicate) {
         var timeout = 5000
         var i = 0
@@ -87,5 +91,8 @@ WebEngineView {
             viewportReady = false
     }
 
+    onWindowCloseRequested: {
+        windowCloseRequestedSignalEmitted = true;
+    }
 }
 
diff --git a/tests/auto/quick/qmltests/data/confirmclose.html b/tests/auto/quick/qmltests/data/confirmclose.html
new file mode 100644
index 0000000000000000000000000000000000000000..ba11da7a4f5ffe0a583d9987e8502836b0054c75
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/confirmclose.html
@@ -0,0 +1,5 @@
+<html>
+<body onbeforeunload="return 'You are about to miss out on some awesome content.';">
+    Be greeted, precious viewer!
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
index 75b45bfac35197d420dde3f40dad4d8926ac983c..4294c5ba369229f77e99d557236dd447bb8b13f1 100644
--- a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
+++ b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
@@ -42,11 +42,26 @@
 import QtQuick 2.0
 import QtTest 1.0
 import QtWebEngine 1.2
+import QtWebEngine.testsupport 1.0
 import "../mock-delegates/TestParams" 1.0
 
 TestWebEngineView {
     id: webEngineView
 
+    testSupport: WebEngineTestSupport {
+        property bool windowCloseRejectedSignalEmitted: false
+
+        function waitForWindowCloseRejected() {
+            return _waitFor(function () {
+                    return testSupport.windowCloseRejectedSignalEmitted;
+                });
+        }
+
+        onWindowCloseRejected: {
+            windowCloseRejectedSignalEmitted = true;
+        }
+    }
+
     TestCase {
         id: test
         name: "WebEngineViewJavaScriptDialogs"
@@ -80,6 +95,24 @@ TestWebEngineView {
 
         }
 
+        function test_confirmClose() {
+            webEngineView.url = Qt.resolvedUrl("confirmclose.html");
+            verify(webEngineView.waitForLoadSucceeded());
+            webEngineView.windowCloseRequestedSignalEmitted = false;
+            JSDialogParams.shouldAcceptDialog = true;
+            webEngineView.triggerWebAction(WebEngineView.RequestClose);
+            verify(webEngineView.waitForWindowCloseRequested());
+        }
+
+        function test_rejectClose() {
+            webEngineView.url = Qt.resolvedUrl("confirmclose.html");
+            verify(webEngineView.waitForLoadSucceeded());
+            webEngineView.testSupport.windowCloseRejectedSignalEmitted = false;
+            JSDialogParams.shouldAcceptDialog = false;
+            webEngineView.triggerWebAction(WebEngineView.RequestClose);
+            verify(webEngineView.testSupport.waitForWindowCloseRejected());
+        }
+
         function test_prompt() {
             JSDialogParams.inputForPrompt = "tQ olleH"
             webEngineView.url = Qt.resolvedUrl("prompt.html")
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 01517af47b9d8c66e964657ed007dcb62e622315..57649384d49f93d17c40cb74122f31c6186fd60e 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -12,6 +12,7 @@ OTHER_FILES += \
     $$PWD/data/change-document-title.js \
     $$PWD/data/download.zip \
     $$PWD/data/confirm.html \
+    $$PWD/data/confirmclose.html \
     $$PWD/data/directoryupload.html \
     $$PWD/data/favicon.html \
     $$PWD/data/favicon.png \