summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/core_gyp_generator.pro2
-rw-r--r--src/core/network_delegate_qt.cpp140
-rw-r--r--src/core/network_delegate_qt.h38
-rw-r--r--src/core/web_contents_adapter_client.h16
-rw-r--r--src/webengine/api/qquickwebenginenavigationrequest.cpp111
-rw-r--r--src/webengine/api/qquickwebenginenavigationrequest_p.h85
-rw-r--r--src/webengine/api/qquickwebengineview.cpp10
-rw-r--r--src/webengine/api/qquickwebengineview_p.h22
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h1
-rw-r--r--src/webengine/plugin/plugin.cpp2
-rw-r--r--src/webengine/webengine.pro2
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h1
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp10
-rw-r--r--tests/auto/quick/qmltests/data/test2.html3
-rw-r--r--tests/auto/quick/qmltests/data/tst_navigationRequested.qml154
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro1
16 files changed, 580 insertions, 18 deletions
diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index 27ee33e51..5e6d08214 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -55,6 +55,7 @@ SOURCES = \
javascript_dialog_controller.cpp \
javascript_dialog_manager_qt.cpp \
media_capture_devices_dispatcher.cpp \
+ network_delegate_qt.cpp \
ozone_platform_eglfs.cpp \
process_main.cpp \
qrc_protocol_handler_qt.cpp \
@@ -99,6 +100,7 @@ HEADERS = \
javascript_dialog_controller.h \
javascript_dialog_manager_qt.h \
media_capture_devices_dispatcher.h \
+ network_delegate_qt.h \
ozone_platform_eglfs.h \
process_main.h \
qrc_protocol_handler_qt.h \
diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp
index 27807c499..424d0e631 100644
--- a/src/core/network_delegate_qt.cpp
+++ b/src/core/network_delegate_qt.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -40,3 +40,141 @@
****************************************************************************/
#include "network_delegate_qt.h"
+
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/resource_request_details.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/page_transition_types.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_request.h"
+#include "type_conversion.h"
+#include "web_contents_adapter_client.h"
+#include "web_contents_view_qt.h"
+
+namespace {
+
+int pageTransitionToNavigationType(content::PageTransition transition)
+{
+ int32 qualifier = content::PageTransitionGetQualifier(transition);
+
+ if (qualifier & content::PAGE_TRANSITION_FORWARD_BACK)
+ return WebContentsAdapterClient::BackForwardNavigation;
+
+ content::PageTransition stippedTransition = content::PageTransitionStripQualifier(transition);
+
+ switch (stippedTransition) {
+ case content::PAGE_TRANSITION_LINK:
+ return WebContentsAdapterClient::LinkClickedNavigation;
+ case content::PAGE_TRANSITION_TYPED:
+ return WebContentsAdapterClient::TypedNavigation;
+ case content::PAGE_TRANSITION_FORM_SUBMIT:
+ return WebContentsAdapterClient::FormSubmittedNavigation;
+ case content::PAGE_TRANSITION_RELOAD:
+ return WebContentsAdapterClient::ReloadNavigation;
+ default:
+ return WebContentsAdapterClient::OtherNavigation;
+ }
+}
+
+}
+
+int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ const content::ResourceRequestInfo *info = content::ResourceRequestInfo::ForRequest(request);
+ int renderProcessId;
+ int renderViewId;
+ if (!info || !info->GetRenderViewForRequest(request, &renderProcessId, &renderViewId))
+ // Abort the request if it has no associated render info / render view.
+ return net::ERR_ABORTED;
+
+ ResourceType::Type resourceType = info->GetResourceType();
+ // Only intercept MAIN_FRAME and SUB_FRAME.
+ if (!ResourceType::IsFrame(resourceType))
+ return net::OK;
+
+ // Track active requests since |callback| and |new_url| are valid
+ // only until OnURLRequestDestroyed is called for this request.
+ m_activeRequests.insert(request);
+
+ int navigationType = pageTransitionToNavigationType(info->GetPageTransition());
+
+ RequestParams params = {
+ toQt(request->url()),
+ resourceType == ResourceType::MAIN_FRAME,
+ navigationType,
+ renderProcessId,
+ renderViewId
+ };
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&NetworkDelegateQt::NotifyNavigationRequestedOnUIThread,
+ base::Unretained(this),
+ request,
+ params,
+ callback)
+ );
+
+ // We'll run the callback after we notified the UI thread.
+ return net::ERR_IO_PENDING;
+}
+
+void NetworkDelegateQt::OnURLRequestDestroyed(net::URLRequest* request)
+{
+ m_activeRequests.remove(request);
+}
+
+void NetworkDelegateQt::CompleteURLRequestOnIOThread(net::URLRequest *request,
+ int navigationRequestAction,
+ const net::CompletionCallback &callback)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (!m_activeRequests.contains(request))
+ return;
+
+ int error = net::OK;
+ switch (navigationRequestAction) {
+ case WebContentsAdapterClient::AcceptRequest:
+ error = net::OK;
+ break;
+ case WebContentsAdapterClient::IgnoreRequest:
+ error = net::OK;
+ // We can cancel the request here since we are on the IO thread.
+ request->Cancel();
+ break;
+ default:
+ error = net::ERR_FAILED;
+ Q_UNREACHABLE();
+ }
+ callback.Run(error);
+}
+
+void NetworkDelegateQt::NotifyNavigationRequestedOnUIThread(net::URLRequest *request,
+ RequestParams params,
+ const net::CompletionCallback &callback)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
+ content::RenderViewHost *rvh = content::RenderViewHost::FromID(params.renderProcessId, params.renderViewId);
+
+ if (rvh) {
+ content::WebContents *webContents = content::WebContents::FromRenderViewHost(rvh);
+ WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client();
+ client->navigationRequested(params.navigationType, params.url, navigationRequestAction, params.isMainFrameRequest);
+ }
+
+ // Run the callback on the IO thread.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&NetworkDelegateQt::CompleteURLRequestOnIOThread,
+ base::Unretained(this),
+ request,
+ navigationRequestAction,
+ callback)
+ );
+}
diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h
index 9413addb3..d057b9915 100644
--- a/src/core/network_delegate_qt.h
+++ b/src/core/network_delegate_qt.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -42,22 +42,20 @@
#define NETWORK_DELEGATE_QT_H
#include "net/base/network_delegate.h"
+#include "net/base/net_errors.h"
-#include "qglobal.h"
+#include <QUrl>
+#include <QSet>
+#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
class NetworkDelegateQt : public net::NetworkDelegate {
public:
NetworkDelegateQt() {}
virtual ~NetworkDelegateQt() {}
-
- private:
- // net::NetworkDelegate implementation.
- virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) Q_DECL_OVERRIDE
- {
- return net::OK;
- }
-
+private:
+ // net::NetworkDelegate implementation
+ virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) Q_DECL_OVERRIDE;
virtual int OnBeforeSendHeaders(net::URLRequest* request, const net::CompletionCallback& callback, net::HttpRequestHeaders* headers) Q_DECL_OVERRIDE
{
return net::OK;
@@ -72,7 +70,7 @@ public:
virtual void OnResponseStarted(net::URLRequest* request) Q_DECL_OVERRIDE { }
virtual void OnRawBytesRead(const net::URLRequest& request, int bytes_read) Q_DECL_OVERRIDE { }
virtual void OnCompleted(net::URLRequest* request, bool started) Q_DECL_OVERRIDE { }
- virtual void OnURLRequestDestroyed(net::URLRequest* request) Q_DECL_OVERRIDE { }
+ virtual void OnURLRequestDestroyed(net::URLRequest* request) Q_DECL_OVERRIDE;
virtual void OnPACScriptError(int line_number, const base::string16& error) Q_DECL_OVERRIDE { }
virtual AuthRequiredResponse OnAuthRequired(net::URLRequest* request, const net::AuthChallengeInfo& auth_info,
@@ -84,6 +82,24 @@ public:
virtual bool OnCanThrottleRequest(const net::URLRequest& request) const Q_DECL_OVERRIDE { return false; }
virtual int OnBeforeSocketStreamConnect(net::SocketStream* stream, const net::CompletionCallback& callback) Q_DECL_OVERRIDE { return net::OK; }
virtual void OnRequestWaitStateChange(const net::URLRequest& request, RequestWaitState state) Q_DECL_OVERRIDE { }
+
+ struct RequestParams {
+ QUrl url;
+ bool isMainFrameRequest;
+ int navigationType;
+ int renderProcessId;
+ int renderViewId;
+ };
+
+ void NotifyNavigationRequestedOnUIThread(net::URLRequest *request,
+ RequestParams params,
+ const net::CompletionCallback &callback);
+
+ void CompleteURLRequestOnIOThread(net::URLRequest *request,
+ int navigationRequestAction,
+ const net::CompletionCallback &callback);
+
+ QSet<net::URLRequest *> m_activeRequests;
};
#endif // NETWORK_DELEGATE_QT_H
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index f8f729f60..2dffb8fb5 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -110,6 +110,21 @@ public:
Save
};
+ enum NavigationRequestAction {
+ AcceptRequest,
+ // Make room in the valid range of the enum for extra actions exposed in Experimental.
+ IgnoreRequest = 0xFF
+ };
+
+ enum NavigationType {
+ LinkClickedNavigation,
+ TypedNavigation,
+ FormSubmittedNavigation,
+ BackForwardNavigation,
+ ReloadNavigation,
+ OtherNavigation
+ };
+
enum JavaScriptConsoleMessageLevel {
Info = 0,
Warning,
@@ -144,6 +159,7 @@ public:
virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect & initialGeometry) = 0;
virtual void close() = 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;
virtual bool isFullScreen() const = 0;
virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0;
diff --git a/src/webengine/api/qquickwebenginenavigationrequest.cpp b/src/webengine/api/qquickwebenginenavigationrequest.cpp
new file mode 100644
index 000000000..519170510
--- /dev/null
+++ b/src/webengine/api/qquickwebenginenavigationrequest.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwebenginenavigationrequest_p.h"
+
+#include "qquickwebengineview_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWebEngineNavigationRequestPrivate {
+public:
+ QQuickWebEngineNavigationRequestPrivate(const QUrl& url, QQuickWebEngineView::NavigationType navigationType, bool mainFrame)
+ : url(url)
+ , action(QQuickWebEngineView::AcceptRequest)
+ , navigationType(navigationType)
+ , isMainFrame(mainFrame)
+ {
+ }
+
+ ~QQuickWebEngineNavigationRequestPrivate()
+ {
+ }
+
+ QUrl url;
+ QQuickWebEngineView::NavigationRequestAction action;
+ QQuickWebEngineView::NavigationType navigationType;
+ bool isMainFrame;
+};
+
+QQuickWebEngineNavigationRequest::QQuickWebEngineNavigationRequest(const QUrl& url, QQuickWebEngineView::NavigationType navigationType, bool mainFrame, QObject* parent)
+ : QObject(parent)
+ , d_ptr(new QQuickWebEngineNavigationRequestPrivate(url, navigationType, mainFrame))
+{
+}
+
+QQuickWebEngineNavigationRequest::~QQuickWebEngineNavigationRequest()
+{
+}
+
+void QQuickWebEngineNavigationRequest::setAction(QQuickWebEngineView::NavigationRequestAction action)
+{
+ Q_D(QQuickWebEngineNavigationRequest);
+ if (d->action == action)
+ return;
+
+ d->action = action;
+ emit actionChanged();
+}
+
+QUrl QQuickWebEngineNavigationRequest::url() const
+{
+ Q_D(const QQuickWebEngineNavigationRequest);
+ return d->url;
+}
+
+QQuickWebEngineView::NavigationRequestAction QQuickWebEngineNavigationRequest::action() const
+{
+ Q_D(const QQuickWebEngineNavigationRequest);
+ return d->action;
+}
+
+QQuickWebEngineView::NavigationType QQuickWebEngineNavigationRequest::navigationType() const
+{
+ Q_D(const QQuickWebEngineNavigationRequest);
+ return d->navigationType;
+}
+
+bool QQuickWebEngineNavigationRequest::isMainFrame() const
+{
+ Q_D(const QQuickWebEngineNavigationRequest);
+ return d->isMainFrame;
+}
+
+QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginenavigationrequest_p.h b/src/webengine/api/qquickwebenginenavigationrequest_p.h
new file mode 100644
index 000000000..e8d94a56b
--- /dev/null
+++ b/src/webengine/api/qquickwebenginenavigationrequest_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINENAVIGATIONREQUEST_P_H
+#define QQUICKWEBENGINENAVIGATIONREQUEST_P_H
+
+#include "qtwebengineglobal_p.h"
+#include "qquickwebengineview_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWebEngineNavigationRequestPrivate;
+
+class Q_WEBENGINE_EXPORT QQuickWebEngineNavigationRequest : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QUrl url READ url CONSTANT FINAL)
+ Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL)
+ Q_PROPERTY(QQuickWebEngineView::NavigationRequestAction action READ action WRITE setAction NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QQuickWebEngineView::NavigationType navigationType READ navigationType CONSTANT FINAL)
+
+public:
+ QQuickWebEngineNavigationRequest(const QUrl& url, QQuickWebEngineView::NavigationType navigationType, bool mainFrame, QObject* parent = 0);
+ ~QQuickWebEngineNavigationRequest();
+
+ QUrl url() const;
+ bool isMainFrame() const;
+ QQuickWebEngineView::NavigationRequestAction action() const;
+
+ void setAction(QQuickWebEngineView::NavigationRequestAction action);
+ QQuickWebEngineView::NavigationType navigationType() const;
+
+Q_SIGNALS:
+ void actionChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QQuickWebEngineNavigationRequest)
+ QScopedPointer<QQuickWebEngineNavigationRequestPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickWebEngineNavigationRequest)
+
+#endif // QQUICKWEBENGINENAVIGATIONREQUEST_P_H
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index a6a11c07d..f4881e8a5 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -45,6 +45,7 @@
#include "javascript_dialog_controller.h"
#include "qquickwebenginehistory_p.h"
#include "qquickwebengineloadrequest_p.h"
+#include "qquickwebenginenavigationrequest_p.h"
#include "qquickwebenginenewviewrequest_p.h"
#include "render_widget_host_view_qt_delegate_quick.h"
#include "render_widget_host_view_qt_delegate_quickwindow.h"
@@ -194,6 +195,15 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
return true;
}
+void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame)
+{
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineNavigationRequest navigationRequest(url, static_cast<QQuickWebEngineView::NavigationType>(navigationType), isMainFrame);
+ Q_EMIT q->navigationRequested(&navigationRequest);
+
+ navigationRequestAction = navigationRequest.action();
+}
+
void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog)
{
ui()->showDialog(dialog);
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 12b9ee163..59349954f 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
class QQuickWebEngineViewExperimental;
class QQuickWebEngineViewPrivate;
class QQuickWebEngineLoadRequest;
+class QQuickWebEngineNavigationRequest;
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
Q_OBJECT
@@ -60,6 +61,8 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY loadingChanged)
Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY loadingChanged)
+ Q_ENUMS(NavigationRequestAction);
+ Q_ENUMS(NavigationType);
Q_ENUMS(LoadStatus);
Q_ENUMS(ErrorDomain);
Q_ENUMS(NewViewDestination);
@@ -80,6 +83,24 @@ public:
QQuickWebEngineViewExperimental *experimental() const;
+ // must match WebContentsAdapterClient::NavigationRequestAction
+ enum NavigationRequestAction {
+ AcceptRequest,
+ // Make room in the valid range of the enum so
+ // we can expose extra actions in experimental.
+ IgnoreRequest = 0xFF
+ };
+
+ // must match WebContentsAdapterClient::NavigationType
+ enum NavigationType {
+ LinkClickedNavigation,
+ TypedNavigation,
+ FormSubmittedNavigation,
+ BackForwardNavigation,
+ ReloadNavigation,
+ OtherNavigation
+ };
+
enum LoadStatus {
LoadStartedStatus,
LoadStoppedStatus,
@@ -124,6 +145,7 @@ Q_SIGNALS:
void loadingChanged(QQuickWebEngineLoadRequest *loadRequest);
void loadProgressChanged();
void linkHovered(const QUrl &hoveredUrl);
+ void navigationRequested(QQuickWebEngineNavigationRequest *request);
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID);
protected:
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 25b20a0e8..89d67bcd8 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -160,6 +160,7 @@ public:
virtual void requestFullScreen(bool) Q_DECL_OVERRIDE;
virtual bool isFullScreen() const Q_DECL_OVERRIDE;
virtual bool contextMenuRequested(const WebEngineContextMenuData &) Q_DECL_OVERRIDE;
+ virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE;
virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) Q_DECL_OVERRIDE;
virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) Q_DECL_OVERRIDE;
virtual void didRunJavaScript(quint64, const QVariant&) Q_DECL_OVERRIDE;
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index 811f85dde..478a51f1a 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -44,6 +44,7 @@
#include "qtwebengineversion.h"
#include "qquickwebengineview_p.h"
#include "qquickwebengineloadrequest_p.h"
+#include "qquickwebenginenavigationrequest_p.h"
#include "qquickwebenginenewviewrequest_p.h"
QT_BEGIN_NAMESPACE
@@ -63,6 +64,7 @@ public:
qmlRegisterType<QQuickWebEngineView>(uri, 0, 9, "WebEngineView");
qmlRegisterUncreatableType<QQuickWebEngineLoadRequest>(uri, 0, 9, "WebEngineLoadRequest", QObject::tr("Cannot create separate instance of WebEngineLoadRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineNavigationRequest>(uri, 0, 9, "WebEngineNavigationRequest", QObject::tr("Cannot create separate instance of WebEngineNavigationRequest"));
qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 0, 9, "WebEngineNewViewRequest", QObject::tr("Cannot create separate instance of WebEngineNewViewRequest"));
// The QML type loader relies on the minimum and maximum minor version of registered types
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index c379e2eda..6f2434700 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -15,6 +15,7 @@ INCLUDEPATH += $$PWD api ../core
SOURCES = \
api/qquickwebenginehistory.cpp \
api/qquickwebengineloadrequest.cpp \
+ api/qquickwebenginenavigationrequest.cpp \
api/qquickwebenginenewviewrequest.cpp \
api/qquickwebengineview.cpp \
api/qtwebengineglobal.cpp \
@@ -27,6 +28,7 @@ HEADERS = \
api/qtwebengineglobal_p.h \
api/qquickwebenginehistory_p.h \
api/qquickwebengineloadrequest_p.h \
+ api/qquickwebenginenavigationrequest_p.h \
api/qquickwebenginenewviewrequest_p.h \
api/qquickwebengineview_p.h \
api/qquickwebengineview_p_p.h \
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 90924bd8d..1a5e1ae3c 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -127,6 +127,7 @@ public:
virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &initialGeometry) Q_DECL_OVERRIDE;
virtual void close() Q_DECL_OVERRIDE;
virtual bool contextMenuRequested(const 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 { }
virtual bool isFullScreen() const Q_DECL_OVERRIDE { return false; }
virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) Q_DECL_OVERRIDE;
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 57b6e9001..ad54bd12e 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -47,8 +47,7 @@
#include <QtTest/QtTest>
#include <private/qquickwebengineview_p.h>
#include <private/qquickwebengineloadrequest_p.h>
-// FIXME: Implement!
-// #include <qquickwebenginenavigationrequest_p.h>
+#include <private/qquickwebenginenavigationrequest_p.h>
class tst_publicapi : public QObject {
Q_OBJECT
@@ -59,7 +58,7 @@ private Q_SLOTS:
static QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *>()
<< &QQuickWebEngineView::staticMetaObject
<< &QQuickWebEngineLoadRequest::staticMetaObject
- // << &QQuickWebEngineNavigationRequest::staticMetaObject
+ << &QQuickWebEngineNavigationRequest::staticMetaObject
;
static QList<const char *> knownEnumNames = QList<const char *>();
@@ -79,10 +78,10 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.FtpErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.DnsErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.LinkClickedNavigation --> NavigationType"
+ << "QQuickWebEngineView.TypedNavigation --> NavigationType"
<< "QQuickWebEngineView.FormSubmittedNavigation --> NavigationType"
<< "QQuickWebEngineView.BackForwardNavigation --> NavigationType"
<< "QQuickWebEngineView.ReloadNavigation --> NavigationType"
- << "QQuickWebEngineView.FormResubmittedNavigation --> NavigationType"
<< "QQuickWebEngineView.OtherNavigation --> NavigationType"
<< "QQuickWebEngineView.NewViewInWindow --> NewViewDestination"
<< "QQuickWebEngineView.NewViewInTab --> NewViewDestination"
@@ -118,8 +117,7 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineLoadRequest.errorDomain --> QQuickWebEngineView::ErrorDomain"
<< "QQuickWebEngineLoadRequest.errorCode --> int"
<< "QQuickWebEngineNavigationRequest.url --> QUrl"
- << "QQuickWebEngineNavigationRequest.mouseButton --> int"
- << "QQuickWebEngineNavigationRequest.keyboardModifiers --> int"
+ << "QQuickWebEngineNavigationRequest.isMainFrame --> bool"
<< "QQuickWebEngineNavigationRequest.action --> QQuickWebEngineView::NavigationRequestAction"
<< "QQuickWebEngineNavigationRequest.navigationType --> QQuickWebEngineView::NavigationType"
<< "QQuickWebEngineNavigationRequest.actionChanged() --> void"
diff --git a/tests/auto/quick/qmltests/data/test2.html b/tests/auto/quick/qmltests/data/test2.html
index 629c2a063..8e20d7e9e 100644
--- a/tests/auto/quick/qmltests/data/test2.html
+++ b/tests/auto/quick/qmltests/data/test2.html
@@ -2,5 +2,8 @@
<head><title>Test page with huge link area</title></head>
<body>
<a title="A title" href="test1.html"><img width=200 height=200></a>
+<div>
+ <iframe src="test1.html"></iframe>
+</div>
</body>
</html>
diff --git a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
new file mode 100644
index 000000000..aae3799bc
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 0.9
+
+TestWebEngineView {
+ id: webEngineView
+ width: 200
+ height: 400
+
+ property bool shouldIgnoreLinkClicks: false
+ property bool shouldIgnoreSubFrameRequests: false
+
+ QtObject {
+ id: attributes
+ property url mainUrl: ""
+ property url iframeUrl: ""
+ property bool linkClickedNavigationRequested: false
+ property bool linkClickedNavigationIgnored: false
+
+ function clear() {
+ mainUrl = ""
+ iframeUrl = ""
+ linkClickedNavigationRequested = false
+ linkClickedNavigationIgnored = false
+ }
+ }
+
+ SignalSpy {
+ id: navigationSpy
+ target: webEngineView
+ signalName: "navigationRequested"
+ }
+
+ onNavigationRequested: {
+ if (request.isMainFrame) {
+ attributes.mainUrl = request.url
+ } else {
+ attributes.iframeUrl = request.url
+ if (shouldIgnoreSubFrameRequests) {
+ request.action = WebEngineView.IgnoreRequest
+ }
+ }
+
+ if (request.navigationType === WebEngineView.LinkClickedNavigation) {
+ attributes.linkClickedNavigationRequested = true
+ if (shouldIgnoreLinkClicks) {
+ request.action = WebEngineView.IgnoreRequest
+ attributes.linkClickedNavigationIgnored = true
+ }
+ }
+ }
+
+ TestCase {
+ name: "WebEngineViewNavigationRequested"
+ when: windowShown
+
+ function init() {
+ attributes.clear()
+ navigationSpy.clear()
+ shouldIgnoreLinkClicks = false
+ shouldIgnoreSubFrameRequests = false
+ }
+
+ function test_navigationRequested() {
+ // Test if we get notified about main frame and iframe loads
+ compare(navigationSpy.count, 0)
+ webEngineView.url = Qt.resolvedUrl("test2.html")
+ navigationSpy.wait()
+ compare(attributes.mainUrl, Qt.resolvedUrl("test2.html"))
+ navigationSpy.wait()
+ compare(attributes.iframeUrl, Qt.resolvedUrl("test1.html"))
+ compare(navigationSpy.count, 2)
+ verify(webEngineView.waitForLoadSucceeded())
+
+ // Test if we get notified about clicked links
+ mouseClick(webEngineView, 100, 100)
+ tryCompare(navigationSpy, "count", 3)
+ compare(attributes.mainUrl, Qt.resolvedUrl("test1.html"))
+ verify(attributes.linkClickedNavigationRequested)
+ verify(webEngineView.waitForLoadSucceeded())
+ }
+
+ function test_ignoreLinkClickedRequest() {
+ // Test if we can ignore clicked link requests
+ compare(navigationSpy.count, 0)
+ webEngineView.url = Qt.resolvedUrl("test2.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ shouldIgnoreLinkClicks = true
+ mouseClick(webEngineView, 100, 100)
+ tryCompare(navigationSpy, "count", 3)
+ compare(attributes.mainUrl, Qt.resolvedUrl("test1.html"))
+ verify(attributes.linkClickedNavigationRequested)
+ verify(attributes.linkClickedNavigationIgnored)
+ // We ignored the main frame request, so we should
+ // get notified that the load has been stopped.
+ verify(webEngineView.waitForLoadStopped())
+ verify(!webEngineView.loading)
+ }
+
+ function test_ignoreSubFrameRequest() {
+ // Test if we can ignore sub frame requests
+ shouldIgnoreSubFrameRequests = true
+ webEngineView.url = Qt.resolvedUrl("test2.html")
+ tryCompare(navigationSpy, "count", 2)
+ compare(attributes.mainUrl, Qt.resolvedUrl("test2.html"))
+ compare(attributes.iframeUrl, Qt.resolvedUrl("test1.html"))
+ // We ignored the sub frame request, so
+ // the main frame load should still succeed.
+ verify(webEngineView.waitForLoadSucceeded())
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index e6a68b950..b4514edc9 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -27,6 +27,7 @@ OTHER_FILES += \
$$PWD/data/tst_loadProgressSignal.qml \
$$PWD/data/tst_loadUrl.qml \
$$PWD/data/tst_navigationHistory.qml \
+ $$PWD/data/tst_navigationRequested.qml \
$$PWD/data/tst_properties.qml \
$$PWD/data/tst_runJavaScript.qml \
$$PWD/data/tst_titleChanged.qml