Diff
Modified: trunk/Source/WebKit2/ChangeLog (101085 => 101086)
--- trunk/Source/WebKit2/ChangeLog 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/ChangeLog 2011-11-23 16:52:54 UTC (rev 101086)
@@ -1,5 +1,36 @@
2011-11-22 Caio Marcelo de Oliveira Filho <[email protected]>
+ [Qt] [WK2] Expose onNavigationRequested signal instead of expecting a slot be defined from QML
+ https://bugs.webkit.org/show_bug.cgi?id=72976
+
+ Reviewed by Tor Arne Vestbø.
+
+ Expecting slots/methods to be implemented in QML isn't very idiomatic in
+ comparison with the alternative of having a signal. So we now use a signal
+ for handling navigation requests, and expose a 'request' object with relevant
+ metadata. There's also a settable property 'action' used to indicate whether
+ the navigation should be ignored or trigger a download.
+
+ The pattern signal with an object parameter that can keep the reply is common in QML,
+ and used for example for mouse signals.
+
+ * UIProcess/API/qt/qquickwebview.cpp:
+ * UIProcess/API/qt/qquickwebview_p.h:
+ * UIProcess/API/qt/qquickwebview_p_p.h:
+ * UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationRequested.qml: Renamed from Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationPolicyForUrl.qml.
+ * UIProcess/API/qt/tests/qmltests/qmltests.pro:
+ * UIProcess/qt/QtWebPagePolicyClient.cpp:
+ (NavigationRequest::NavigationRequest):
+ (NavigationRequest::url):
+ (NavigationRequest::button):
+ (NavigationRequest::modifiers):
+ (NavigationRequest::action):
+ (NavigationRequest::setAction):
+ (QtWebPagePolicyClient::decidePolicyForNavigationAction):
+ * UIProcess/qt/QtWebPagePolicyClient.h:
+
+2011-11-22 Caio Marcelo de Oliveira Filho <[email protected]>
+
[Qt] [WK2] Move PagePolicyClient related code to QtWebPagePolicyClient
https://bugs.webkit.org/show_bug.cgi?id=72959
Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp 2011-11-23 16:52:54 UTC (rev 101086)
@@ -344,47 +344,18 @@
attached->setView(q);
}
-static QtWebPagePolicyClient::PolicyAction toPolicyAction(QQuickWebView::NavigationPolicy policy)
-{
- switch (policy) {
- case QQuickWebView::UsePolicy:
- return QtWebPagePolicyClient::Use;
- case QQuickWebView::DownloadPolicy:
- return QtWebPagePolicyClient::Download;
- case QQuickWebView::IgnorePolicy:
- return QtWebPagePolicyClient::Ignore;
- }
- ASSERT_NOT_REACHED();
- return QtWebPagePolicyClient::Ignore;
-}
-
-static bool hasMetaMethod(QObject* object, const char* methodName)
-{
- int methodIndex = object->metaObject()->indexOfMethod(QMetaObject::normalizedSignature(methodName));
- return methodIndex >= 0 && methodIndex < object->metaObject()->methodCount();
-}
-
/*!
- \qmlmethod NavigationPolicy DesktopWebView::navigationPolicyForUrl(url, button, modifiers)
+ \qmlsignal WebView::onNavigationRequested(request)
- This method should be implemented by the user of DesktopWebView element.
+ This signal is emitted for every navigation request. The request object contains url, button and modifiers properties
+ describing the navigation action, e.g. "a middle click with shift key pressed to 'http://qt-project.org'".
- It will be called to decide the policy for a navigation: whether the WebView should ignore the navigation,
- continue it or start a download. The return value must be one of the policies in the NavigationPolicy enumeration.
+ The navigation will be accepted by default. To change that, one can set the action property to WebView.IgnoreRequest to reject
+ the request or WebView.DownloadRequest to trigger a download instead of navigating to the url.
+
+ The request object cannot be used after the signal handler function ends.
*/
-QtWebPagePolicyClient::PolicyAction QQuickWebViewPrivate::navigationPolicyForURL(const QUrl& url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
-{
- Q_Q(QQuickWebView);
- // We need to check this first because invokeMethod() warns if the method doesn't exist for the object.
- if (!hasMetaMethod(q, "navigationPolicyForUrl(QVariant,QVariant,QVariant)"))
- return QtWebPagePolicyClient::Use;
- QVariant ret;
- if (QMetaObject::invokeMethod(q, "navigationPolicyForUrl", Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, url), Q_ARG(QVariant, button), Q_ARG(QVariant, QVariant(modifiers))))
- return toPolicyAction(static_cast<QQuickWebView::NavigationPolicy>(ret.toInt()));
- return QtWebPagePolicyClient::Use;
-}
-
void QQuickWebViewPrivate::setPageProxy(QtWebPageProxy* pageProxy)
{
Q_Q(QQuickWebView);
Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h 2011-11-23 16:52:54 UTC (rev 101086)
@@ -56,13 +56,14 @@
Q_PROPERTY(bool canReload READ canReload NOTIFY navigationStateChanged FINAL)
Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL)
Q_PROPERTY(QQuickWebPage* page READ page CONSTANT FINAL)
- Q_ENUMS(NavigationPolicy)
+ Q_ENUMS(NavigationRequestAction)
Q_ENUMS(ErrorType)
+
public:
- enum NavigationPolicy {
- UsePolicy,
- DownloadPolicy,
- IgnorePolicy
+ enum NavigationRequestAction {
+ AcceptRequest,
+ IgnoreRequest,
+ DownloadRequest
};
enum ErrorType {
@@ -112,6 +113,7 @@
void linkHovered(const QUrl& url, const QString& title);
void viewModeChanged();
void navigationStateChanged();
+ void navigationRequested(QObject* request);
protected:
virtual void geometryChanged(const QRectF&, const QRectF&);
Modified: trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h 2011-11-23 16:52:54 UTC (rev 101086)
@@ -70,8 +70,6 @@
void _q_onOpenPanelFinished(int result);
void _q_onVisibleChanged();
- QtWebPagePolicyClient::PolicyAction navigationPolicyForURL(const QUrl&, Qt::MouseButton, Qt::KeyboardModifiers);
-
void chooseFiles(WKOpenPanelResultListenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType);
void runJavaScriptAlert(const QString&);
bool runJavaScriptConfirm(const QString&);
Deleted: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationPolicyForUrl.qml (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationPolicyForUrl.qml 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationPolicyForUrl.qml 2011-11-23 16:52:54 UTC (rev 101086)
@@ -1,72 +0,0 @@
-import QtQuick 2.0
-import QtTest 1.0
-import QtWebKit 3.0
-import QtWebKitTest 1.0
-
-Item {
- DesktopWebView {
- id: webView
- width: 200
- height: 200
- function navigationPolicyForUrl(url, button, modifiers) {
- if (button == Qt.MiddleButton && modifiers & Qt.ControlModifier) {
- otherWebView.load(url)
- return DesktopWebView.IgnorePolicy
- }
- return DesktopWebView.UsePolicy
- }
- }
-
- SignalSpy {
- id: spy
- target: webView
- signalName: "loadSucceeded"
- }
-
- DesktopWebView {
- id: otherWebView
- }
-
- SignalSpy {
- id: otherSpy
- target: otherWebView
- signalName: "loadSucceeded"
- }
-
- TestCase {
- name: "DesktopWebViewNavigationPolicyForUrl"
-
- // Delayed windowShown to workaround problems with Qt5 in debug mode.
- when: false
- Timer {
- running: parent.windowShown
- repeat: false
- interval: 1
- onTriggered: parent.when = true
- }
-
- function test_usePolicy() {
- webView.load(Qt.resolvedUrl("../common/test2.html"))
- spy.wait()
- spy.clear()
- compare(spy.count, 0)
- mouseClick(webView, 100, 100, Qt.LeftButton)
- spy.wait()
- compare(spy.count, 1)
- compare(webView.title, "Test page 1")
- }
-
- function test_ignorePolicy() {
- webView.load(Qt.resolvedUrl("../common/test2.html"))
- spy.wait()
- spy.clear()
- compare(spy.count, 0)
- compare(otherSpy.count, 0)
- mouseClick(webView, 100, 100, Qt.MiddleButton, Qt.ControlModifier)
- otherSpy.wait()
- compare(spy.count, 0)
- compare(otherSpy.count, 1)
- compare(otherWebView.title, "Test page 1")
- }
- }
-}
Copied: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationRequested.qml (from rev 101085, trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationPolicyForUrl.qml) (0 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationRequested.qml (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_navigationRequested.qml 2011-11-23 16:52:54 UTC (rev 101086)
@@ -0,0 +1,70 @@
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebKit 3.0
+import QtWebKitTest 1.0
+
+Item {
+ DesktopWebView {
+ id: webView
+ width: 200
+ height: 200
+ onNavigationRequested: {
+ if (request.button == Qt.MiddleButton && request.modifiers & Qt.ControlModifier) {
+ otherWebView.load(request.url)
+ request.action = ""
+ }
+ }
+ }
+
+ SignalSpy {
+ id: spy
+ target: webView
+ signalName: "loadSucceeded"
+ }
+
+ DesktopWebView {
+ id: otherWebView
+ }
+
+ SignalSpy {
+ id: otherSpy
+ target: otherWebView
+ signalName: "loadSucceeded"
+ }
+
+ TestCase {
+ name: "DesktopWebViewNavigationRequested"
+
+ // Delayed windowShown to workaround problems with Qt5 in debug mode.
+ when: false
+ Timer {
+ running: parent.windowShown
+ repeat: false
+ interval: 1
+ onTriggered: parent.when = true
+ }
+
+ function test_usePolicy() {
+ webView.load(Qt.resolvedUrl("../common/test2.html"))
+ spy.wait()
+ spy.clear()
+ mouseClick(webView, 100, 100, Qt.LeftButton)
+ spy.wait()
+ compare(spy.count, 1)
+ compare(webView.title, "Test page 1")
+ }
+
+ function test_ignorePolicy() {
+ webView.load(Qt.resolvedUrl("../common/test2.html"))
+ spy.wait()
+ spy.clear()
+ compare(spy.count, 0)
+ compare(otherSpy.count, 0)
+ mouseClick(webView, 100, 100, Qt.MiddleButton, Qt.ControlModifier)
+ otherSpy.wait()
+ compare(spy.count, 0)
+ compare(otherSpy.count, 1)
+ compare(otherWebView.title, "Test page 1")
+ }
+ }
+}
Modified: trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/API/qt/tests/qmltests/qmltests.pro 2011-11-23 16:52:54 UTC (rev 101086)
@@ -27,5 +27,5 @@
DesktopBehavior/tst_linkHovered.qml \
DesktopBehavior/tst_messaging.qml \
DesktopBehavior/tst_download.qml \
- DesktopBehavior/tst_navigationPolicyForUrl.qml \
+ DesktopBehavior/tst_navigationRequested.qml \
DesktopBehavior/tst_loadHtml.qml
Modified: trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp 2011-11-23 16:52:54 UTC (rev 101086)
@@ -24,9 +24,49 @@
#include "WKURLQt.h"
#include "qquickwebview_p.h"
#include "qquickwebview_p_p.h"
+#include <QtCore/QObject>
#include <WKFramePolicyListener.h>
#include <WKURLRequest.h>
+class NavigationRequest : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QUrl url READ url CONSTANT FINAL)
+ Q_PROPERTY(int button READ button CONSTANT FINAL)
+ Q_PROPERTY(int modifiers READ modifiers CONSTANT FINAL)
+ Q_PROPERTY(int action READ action WRITE setAction NOTIFY actionChanged FINAL)
+
+public:
+ NavigationRequest(const QUrl& url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
+ : m_url(url)
+ , m_button(button)
+ , m_modifiers(modifiers)
+ , m_action(QQuickWebView::AcceptRequest)
+ {
+ }
+
+ QUrl url() const { return m_url; }
+ int button() const { return int(m_button); }
+ int modifiers() const { return int(m_modifiers); }
+
+ int action() const { return int(m_action); }
+ void setAction(int action)
+ {
+ if (m_action == action)
+ return;
+ m_action = action;
+ emit actionChanged();
+ }
+
+Q_SIGNALS:
+ void actionChanged();
+
+private:
+ QUrl m_url;
+ Qt::MouseButton m_button;
+ Qt::KeyboardModifiers m_modifiers;
+ int m_action;
+};
+
QtWebPagePolicyClient::QtWebPagePolicyClient(WKPageRef pageRef, QQuickWebView* webView)
: m_webView(webView)
{
@@ -39,9 +79,25 @@
WKPageSetPagePolicyClient(pageRef, &policyClient);
}
-QtWebPagePolicyClient::PolicyAction QtWebPagePolicyClient::decidePolicyForNavigationAction(const QUrl& url, Qt::MouseButton mouseButton, Qt::KeyboardModifiers keyboardModifiers)
+void QtWebPagePolicyClient::decidePolicyForNavigationAction(const QUrl& url, Qt::MouseButton mouseButton, Qt::KeyboardModifiers keyboardModifiers, WKFramePolicyListenerRef listener)
{
- return m_webView->d_func()->navigationPolicyForURL(url, mouseButton, keyboardModifiers);
+ // NOTE: even though the C API (and the WebKit2 IPC) supports an asynchronous answer, this is not currently working.
+ // We are expected to call the listener immediately. See the patch for https://bugs.webkit.org/show_bug.cgi?id=53785.
+ NavigationRequest navigationRequest(url, mouseButton, keyboardModifiers);
+ emit m_webView->navigationRequested(&navigationRequest);
+
+ switch (QQuickWebView::NavigationRequestAction(navigationRequest.action())) {
+ case QQuickWebView::IgnoreRequest:
+ WKFramePolicyListenerIgnore(listener);
+ return;
+ case QQuickWebView::DownloadRequest:
+ WKFramePolicyListenerDownload(listener);
+ return;
+ case QQuickWebView::AcceptRequest:
+ WKFramePolicyListenerUse(listener);
+ return;
+ }
+ ASSERT_NOT_REACHED();
}
static inline QtWebPagePolicyClient* toQtWebPagePolicyClient(const void* clientInfo)
@@ -85,20 +141,7 @@
WKURLRef requestURL = WKURLRequestCopyURL(request);
QUrl qUrl = WKURLCopyQUrl(requestURL);
WKRelease(requestURL);
-
- PolicyAction action = "" toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers));
- switch (action) {
- case Use:
- WKFramePolicyListenerUse(listener);
- return;
- case Download:
- WKFramePolicyListenerDownload(listener);
- return;
- case Ignore:
- WKFramePolicyListenerIgnore(listener);
- return;
- }
- ASSERT_NOT_REACHED();
+ toQtWebPagePolicyClient(clientInfo)->decidePolicyForNavigationAction(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers), listener);
}
void QtWebPagePolicyClient::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void*)
@@ -128,3 +171,4 @@
WKFramePolicyListenerUse(listener);
}
+#include "QtWebPagePolicyClient.moc"
Modified: trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h (101085 => 101086)
--- trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h 2011-11-23 16:04:50 UTC (rev 101085)
+++ trunk/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h 2011-11-23 16:52:54 UTC (rev 101086)
@@ -30,14 +30,8 @@
public:
QtWebPagePolicyClient(WKPageRef, QQuickWebView*);
- enum PolicyAction {
- Use,
- Download,
- Ignore
- };
-
private:
- PolicyAction decidePolicyForNavigationAction(const QUrl&, Qt::MouseButton, Qt::KeyboardModifiers);
+ void decidePolicyForNavigationAction(const QUrl&, Qt::MouseButton, Qt::KeyboardModifiers, WKFramePolicyListenerRef);
// WKPagePolicyClient callbacks.
static void decidePolicyForNavigationAction(WKPageRef, WKFrameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKURLRequestRef, WKFramePolicyListenerRef, WKTypeRef userData, const void* clientInfo);