diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index bb8c52266d32dc83b800b1b3b880eedbb3a7b33e..6d4315b64f32bc208a87b327208a32310450ad20 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -73,6 +73,17 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view
     new QtRenderViewObserver(render_view);
 }
 
+bool ContentRendererClientQt::HasErrorPage(int httpStatusCode, std::string *errorDomain)
+{
+    // Use an internal error page, if we have one for the status code.
+    if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, httpStatusCode)) {
+        return false;
+    }
+
+    *errorDomain = LocalizedError::kHttpErrorDomain;
+    return true;
+}
+
 // To tap into the chromium localized strings. Ripped from the chrome layer (highly simplified).
 void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderView* render_view, blink::WebFrame *frame, const blink::WebURLRequest &failed_request, const blink::WebURLError &error, std::string *error_html, base::string16 *error_description)
 {
diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h
index af1aa0676344ce33d48896d254301952d4945d6b..386495e20dadc6fc3a83b7388e169f1bc20300c4 100644
--- a/src/core/renderer/content_renderer_client_qt.h
+++ b/src/core/renderer/content_renderer_client_qt.h
@@ -50,7 +50,8 @@ public:
     virtual void RenderThreadStarted() Q_DECL_OVERRIDE;
     virtual void RenderViewCreated(content::RenderView *render_view) Q_DECL_OVERRIDE;
 
-    virtual bool ShouldSuppressErrorPage(content::RenderFrame *, const GURL &) Q_DECL_OVERRIDE { return true; }
+    virtual bool ShouldSuppressErrorPage(content::RenderFrame *, const GURL &) Q_DECL_OVERRIDE { return false; }
+    virtual bool HasErrorPage(int httpStatusCode, std::string *errorDomain) Q_DECL_OVERRIDE;
     virtual void GetNavigationErrorStrings(content::RenderView* render_view, blink::WebFrame* frame, const blink::WebURLRequest& failed_request
             , const blink::WebURLError& error, std::string* error_html, base::string16* error_description) Q_DECL_OVERRIDE;
 
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index e221e0ce89194d48c9ce782bc8e2fa6351c8c9f5..739b3b4239efd9eccbc3d82678bb152798f37568 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -399,12 +399,6 @@ bool WebContentsAdapter::canGoForward() const
     return d->webContents->GetController().CanGoForward();
 }
 
-bool WebContentsAdapter::isLoading() const
-{
-    Q_D(const WebContentsAdapter);
-    return d->webContents->IsLoading();
-}
-
 void WebContentsAdapter::stop()
 {
     Q_D(WebContentsAdapter);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index bddc3e04509d215d5d9a35aabea5b9c1691d06ff..6bec50316408fd809c4b4231ca86477ca2dd1f09 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -64,7 +64,6 @@ public:
 
     bool canGoBack() const;
     bool canGoForward() const;
-    bool isLoading() const;
     void stop();
     void reload();
     void load(const QUrl&);
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 0523d8b2277cd298e96f2bb6868f72d6750ab9cc..5de433b3b231e5a880a82a63ae5837d6466e6a23 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -56,9 +56,9 @@
 #include "content/public/common/favicon_url.h"
 #include "content/public/common/file_chooser_params.h"
 #include "content/public/common/frame_navigate_params.h"
+#include "content/public/common/url_constants.h"
 #include "webkit/common/webpreferences.h"
 
-
 // Maps the LogSeverity defines in base/logging.h to the web engines message levels.
 static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32 messageLevel) {
     if (messageLevel < 1)
@@ -72,6 +72,7 @@ static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptCo
 WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient)
     : m_viewClient(adapterClient)
     , m_lastReceivedFindReply(0)
+    , m_isLoadingErrorPage(false)
 {
     webContents->SetDelegate(this);
     Observe(webContents);
@@ -124,11 +125,16 @@ void WebContentsDelegateQt::CloseContents(content::WebContents *source)
 
 void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, double progress)
 {
+    if (m_isLoadingErrorPage)
+        return;
     m_viewClient->loadProgressChanged(qRound(progress * 100));
 }
 
-void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(int64, int64, bool is_main_frame, const GURL &validated_url, bool, bool, content::RenderViewHost*)
+void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(int64, int64, bool is_main_frame, const GURL &validated_url, bool isErrorPage, bool, content::RenderViewHost*)
 {
+    m_isLoadingErrorPage = isErrorPage;
+    if (isErrorPage)
+        return;
     if (is_main_frame)
         m_viewClient->loadStarted(toQt(validated_url));
 }
@@ -147,15 +153,24 @@ void WebContentsDelegateQt::DidFailProvisionalLoad(int64 frame_id, const base::s
     DidFailLoad(frame_id, validated_url, is_main_frame, error_code, error_description, render_view_host);
 }
 
-void WebContentsDelegateQt::DidFailLoad(int64, const GURL&, bool is_main_frame, int error_code, const base::string16 &error_description, content::RenderViewHost*)
+void WebContentsDelegateQt::DidFailLoad(int64, const GURL&, bool is_main_frame, int error_code, const base::string16 &error_description, content::RenderViewHost *rvh)
 {
-    if (is_main_frame)
-        m_viewClient->loadFinished(false, error_code, toQt(error_description));
+    if (!is_main_frame || m_isLoadingErrorPage)
+        return;
+    m_viewClient->loadFinished(false, error_code, toQt(error_description));
+    m_viewClient->loadProgressChanged(0);
 }
 
-void WebContentsDelegateQt::DidFinishLoad(int64, const GURL&, bool is_main_frame, content::RenderViewHost*)
+void WebContentsDelegateQt::DidFinishLoad(int64, const GURL &url, bool is_main_frame, content::RenderViewHost*)
 {
+    if (m_isLoadingErrorPage) {
+        Q_ASSERT(url.is_valid() && url.spec() == content::kUnreachableWebDataURL);
+        m_viewClient->iconChanged(QUrl());
+        return;
+    }
+
     if (is_main_frame) {
+        m_viewClient->loadProgressChanged(100);
         m_viewClient->loadFinished(true);
 
         content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry();
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index c1f0c4647b53d88c6b2763f916ec340b8945eea1..b7a23d3c275a614613f8def8f1b7cd9aed5c10db 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -94,6 +94,7 @@ private:
     WebContentsAdapterClient *m_viewClient;
     QString m_lastSearchedString;
     int m_lastReceivedFindReply;
+    bool m_isLoadingErrorPage;
 };
 
 #endif // WEB_CONTENTS_DELEGATE_QT_H
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index c9faa1a78451beb0a6269f8328450bf5f9e16c32..bc9a0258e7ffd3f94d41e4281c3c4cdbd0074adb 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -82,6 +82,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
     , loadProgress(0)
     , inspectable(false)
     , m_isFullScreen(false)
+    , isLoading(false)
     , devicePixelRatio(QGuiApplication::primaryScreen()->devicePixelRatio())
     , m_dpiScale(1.0)
 {
@@ -277,6 +278,7 @@ qreal QQuickWebEngineViewPrivate::dpiScale() const
 void QQuickWebEngineViewPrivate::loadStarted(const QUrl &provisionalUrl)
 {
     Q_Q(QQuickWebEngineView);
+    isLoading = true;
     m_history->reset();
     QQuickWebEngineLoadRequest loadRequest(provisionalUrl, QQuickWebEngineView::LoadStartedStatus);
     Q_EMIT q->loadingChanged(&loadRequest);
@@ -299,6 +301,7 @@ Q_STATIC_ASSERT(static_cast<int>(WebEngineError::DnsErrorDomain) == static_cast<
 void QQuickWebEngineViewPrivate::loadFinished(bool success, int error_code, const QString &error_description)
 {
     Q_Q(QQuickWebEngineView);
+    isLoading = false;
     m_history->reset();
     if (error_code == WebEngineError::UserAbortedError) {
         QQuickWebEngineLoadRequest loadRequest(q->url(), QQuickWebEngineView::LoadStoppedStatus);
@@ -571,7 +574,7 @@ void QQuickWebEngineViewPrivate::didFindText(quint64 requestId, int matchCount)
 bool QQuickWebEngineView::isLoading() const
 {
     Q_D(const QQuickWebEngineView);
-    return d->adapter->isLoading();
+    return d->isLoading;
 }
 
 int QQuickWebEngineView::loadProgress() const
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index dc47d63b3450e39006c6fbf935a9f4327d97d643..7f43d7fe6cb175396a2877b79926dd6c8abfb438 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -192,6 +192,7 @@ public:
     int loadProgress;
     bool inspectable;
     bool m_isFullScreen;
+    bool isLoading;
     qreal devicePixelRatio;
     QMap<quint64, QJSValue> m_callbacks;
 
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 51e733e704b7726f6405c01b2db78782f3a27ac5..ac677a8c627f46aefb27153de409a607a3448c71 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -171,6 +171,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate()
     , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
     , settings(new QWebEngineSettings)
     , view(0)
+    , isLoading(false)
 {
     memset(actions, 0, sizeof(actions));
 }
@@ -237,6 +238,7 @@ void QWebEnginePagePrivate::loadStarted(const QUrl &provisionalUrl)
 {
     Q_UNUSED(provisionalUrl)
     Q_Q(QWebEnginePage);
+    isLoading = true;
     Q_EMIT q->loadStarted();
     updateNavigationActions();
 }
@@ -251,6 +253,7 @@ void QWebEnginePagePrivate::loadFinished(bool success, int error_code, const QSt
     Q_Q(QWebEnginePage);
     Q_UNUSED(error_code);
     Q_UNUSED(error_description);
+    isLoading = false;
     if (success)
         m_explicitUrl = QUrl();
     Q_EMIT q->loadFinished(success);
@@ -362,11 +365,11 @@ void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const
         enabled = adapter->canGoForward();
         break;
     case QWebEnginePage::Stop:
-        enabled = adapter->isLoading();
+        enabled = isLoading;
         break;
     case QWebEnginePage::Reload:
     case QWebEnginePage::ReloadAndBypassCache:
-        enabled = !adapter->isLoading();
+        enabled = !isLoading;
         break;
     default:
         break;
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 10a253d8d5b55825091bdf0259cee0ddaa965d56..fab4a2139084ac6f08bddd7ed8672d0178247e50 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -153,6 +153,7 @@ public:
     QSize viewportSize;
     QUrl m_explicitUrl;
     WebEngineContextMenuData m_menuData;
+    bool isLoading;
 
     mutable CallbackDirectory m_callbacks;
     mutable QAction *actions[QWebEnginePage::WebActionCount];
diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
index be7ede6260f5b1e55a095c79ca19d8ca2ac1b54b..41faa6bc37151d04cbf3cd57d7af581a6965f341 100644
--- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
@@ -124,9 +124,9 @@ TestWebEngineView {
 
             var handleLoadFailed = function(loadRequest) {
                 if (loadRequest.status == WebEngineView.LoadFailedStatus) {
+                    webEngineView.loadHtml("load failed", bogusSite)
                     compare(webEngineView.url, bogusSite)
                     compare(loadRequest.url, bogusSite)
-                    webEngineView.loadHtml("load failed", bogusSite)
                 }
             }
             webEngineView.loadingChanged.connect(handleLoadFailed)
@@ -166,8 +166,7 @@ TestWebEngineView {
             }
             lastUrl = webEngineView.url
             webEngineView.loadingChanged.connect(handleLoadRequest)
-            webEngineView.forceActiveFocus()
-            keyPress(Qt.Key_Return) // Link is focused
+            mouseClick(webEngineView, 10, 10, Qt.LeftButton, Qt.NoModifiers, 50)
             verify(webEngineView.waitForLoadSucceeded())
             compare(webEngineView.url, url)
             webEngineView.loadingChanged.disconnect(handleLoadRequest)