Title: [101086] trunk/Source/WebKit2
Revision
101086
Author
[email protected]
Date
2011-11-23 08:52:54 -0800 (Wed, 23 Nov 2011)

Log Message

[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:

Modified Paths

Added Paths

Removed Paths

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);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to