[Qt] [WK2] Expose onNavigationRequested signal instead of expecting a slot be defined...
[WebKit.git] / Source / WebKit2 / UIProcess / qt / QtWebPagePolicyClient.cpp
1 /*
2  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "QtWebPagePolicyClient.h"
23
24 #include "WKURLQt.h"
25 #include "qquickwebview_p.h"
26 #include "qquickwebview_p_p.h"
27 #include <QtCore/QObject>
28 #include <WKFramePolicyListener.h>
29 #include <WKURLRequest.h>
30
31 class NavigationRequest : public QObject {
32     Q_OBJECT
33     Q_PROPERTY(QUrl url READ url CONSTANT FINAL)
34     Q_PROPERTY(int button READ button CONSTANT FINAL)
35     Q_PROPERTY(int modifiers READ modifiers CONSTANT FINAL)
36     Q_PROPERTY(int action READ action WRITE setAction NOTIFY actionChanged FINAL)
37
38 public:
39     NavigationRequest(const QUrl& url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
40         : m_url(url)
41         , m_button(button)
42         , m_modifiers(modifiers)
43         , m_action(QQuickWebView::AcceptRequest)
44     {
45     }
46
47     QUrl url() const { return m_url; }
48     int button() const { return int(m_button); }
49     int modifiers() const { return int(m_modifiers); }
50
51     int action() const { return int(m_action); }
52     void setAction(int action)
53     {
54         if (m_action == action)
55             return;
56         m_action = action;
57         emit actionChanged();
58     }
59
60 Q_SIGNALS:
61     void actionChanged();
62
63 private:
64     QUrl m_url;
65     Qt::MouseButton m_button;
66     Qt::KeyboardModifiers m_modifiers;
67     int m_action;
68 };
69
70 QtWebPagePolicyClient::QtWebPagePolicyClient(WKPageRef pageRef, QQuickWebView* webView)
71     : m_webView(webView)
72 {
73     WKPagePolicyClient policyClient;
74     memset(&policyClient, 0, sizeof(WKPagePolicyClient));
75     policyClient.version = kWKPagePolicyClientCurrentVersion;
76     policyClient.clientInfo = this;
77     policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction;
78     policyClient.decidePolicyForResponse = decidePolicyForResponse;
79     WKPageSetPagePolicyClient(pageRef, &policyClient);
80 }
81
82 void QtWebPagePolicyClient::decidePolicyForNavigationAction(const QUrl& url, Qt::MouseButton mouseButton, Qt::KeyboardModifiers keyboardModifiers, WKFramePolicyListenerRef listener)
83 {
84     // NOTE: even though the C API (and the WebKit2 IPC) supports an asynchronous answer, this is not currently working.
85     // We are expected to call the listener immediately. See the patch for https://bugs.webkit.org/show_bug.cgi?id=53785.
86     NavigationRequest navigationRequest(url, mouseButton, keyboardModifiers);
87     emit m_webView->navigationRequested(&navigationRequest);
88
89     switch (QQuickWebView::NavigationRequestAction(navigationRequest.action())) {
90     case QQuickWebView::IgnoreRequest:
91         WKFramePolicyListenerIgnore(listener);
92         return;
93     case QQuickWebView::DownloadRequest:
94         WKFramePolicyListenerDownload(listener);
95         return;
96     case QQuickWebView::AcceptRequest:
97         WKFramePolicyListenerUse(listener);
98         return;
99     }
100     ASSERT_NOT_REACHED();
101 }
102
103 static inline QtWebPagePolicyClient* toQtWebPagePolicyClient(const void* clientInfo)
104 {
105     ASSERT(clientInfo);
106     return reinterpret_cast<QtWebPagePolicyClient*>(const_cast<void*>(clientInfo));
107 }
108
109 static Qt::MouseButton toQtMouseButton(WKEventMouseButton button)
110 {
111     switch (button) {
112     case kWKEventMouseButtonLeftButton:
113         return Qt::LeftButton;
114     case kWKEventMouseButtonMiddleButton:
115         return Qt::MiddleButton;
116     case kWKEventMouseButtonRightButton:
117         return Qt::RightButton;
118     case kWKEventMouseButtonNoButton:
119         return Qt::NoButton;
120     }
121     ASSERT_NOT_REACHED();
122     return Qt::NoButton;
123 }
124
125 static Qt::KeyboardModifiers toQtKeyboardModifiers(WKEventModifiers modifiers)
126 {
127     Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
128     if (modifiers & kWKEventModifiersShiftKey)
129         qtModifiers |= Qt::ShiftModifier;
130     if (modifiers & kWKEventModifiersControlKey)
131         qtModifiers |= Qt::ControlModifier;
132     if (modifiers & kWKEventModifiersAltKey)
133         qtModifiers |= Qt::AltModifier;
134     if (modifiers & kWKEventModifiersMetaKey)
135         qtModifiers |= Qt::MetaModifier;
136     return qtModifiers;
137 }
138
139 void QtWebPagePolicyClient::decidePolicyForNavigationAction(WKPageRef, WKFrameRef, WKFrameNavigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
140 {
141     WKURLRef requestURL = WKURLRequestCopyURL(request);
142     QUrl qUrl = WKURLCopyQUrl(requestURL);
143     WKRelease(requestURL);
144     toQtWebPagePolicyClient(clientInfo)->decidePolicyForNavigationAction(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers), listener);
145 }
146
147 void QtWebPagePolicyClient::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void*)
148 {
149     String type = toImpl(response)->resourceResponse().mimeType();
150     type.makeLower();
151     bool canShowMIMEType = toImpl(frame)->canShowMIMEType(type);
152
153     if (WKPageGetMainFrame(page) == frame) {
154         if (canShowMIMEType) {
155             WKFramePolicyListenerUse(listener);
156             return;
157         }
158
159         // If we can't use (show) it then we should download it.
160         WKFramePolicyListenerDownload(listener);
161         return;
162     }
163
164     // We should ignore downloadable top-level content for subframes, with an exception for text/xml and application/xml so we can still support Acid3 test.
165     // It makes the browser intentionally behave differently when it comes to text(application)/xml content in subframes vs. mainframe.
166     if (!canShowMIMEType && !(type == "text/xml" || type == "application/xml")) {
167         WKFramePolicyListenerIgnore(listener);
168         return;
169     }
170
171     WKFramePolicyListenerUse(listener);
172 }
173
174 #include "QtWebPagePolicyClient.moc"