0863ec76cc26196e5d432d453bdc617af72e082f
[WebKit.git] / Source / WebKit2 / UIProcess / qt / ClientImpl.cpp
1 /*
2     Copyright (C) 2010 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 library 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 library; 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 #include "config.h"
21 #include "ClientImpl.h"
22
23 #include "QtWebError.h"
24 #include "WebFrameProxy.h"
25 #include "WKAPICast.h"
26 #include "WKStringQt.h"
27 #include "WKURLQt.h"
28 #include <QtPolicyInterface.h>
29 #include <QtWebPageProxy.h>
30 #include <WKArray.h>
31 #include <WKFrame.h>
32 #include <WKFramePolicyListener.h>
33 #include <WKHitTestResult.h>
34 #include <WKPage.h>
35 #include <WKString.h>
36 #include <WKType.h>
37 #include <WKURLRequest.h>
38
39 using namespace WebKit;
40
41 static QtWebPageProxy* toQtWebPageProxy(const void* clientInfo)
42 {
43     if (clientInfo)
44         return reinterpret_cast<QtWebPageProxy*>(const_cast<void*>(clientInfo));
45     return 0;
46 }
47
48 static inline QtPolicyInterface* toQtPolicyInterface(const void* clientInfo)
49 {
50     ASSERT(clientInfo);
51     return reinterpret_cast<QtPolicyInterface*>(const_cast<void*>(clientInfo));
52 }
53
54 static void dispatchLoadSucceeded(WKFrameRef frame, const void* clientInfo)
55 {
56     if (!WKFrameIsMainFrame(frame))
57         return;
58
59     toQtWebPageProxy(clientInfo)->updateNavigationState();
60     toQtWebPageProxy(clientInfo)->loadDidSucceed();
61 }
62
63 static void dispatchLoadFailed(WKFrameRef frame, const void* clientInfo, WKErrorRef error)
64 {
65     if (!WKFrameIsMainFrame(frame))
66         return;
67
68     toQtWebPageProxy(clientInfo)->updateNavigationState();
69
70     int errorCode = WKErrorGetErrorCode(error);
71     if (toImpl(error)->platformError().isCancellation() || errorCode == kWKErrorCodeFrameLoadInterruptedByPolicyChange || errorCode == kWKErrorCodePlugInWillHandleLoad)
72         return;
73
74     toQtWebPageProxy(clientInfo)->loadDidFail(QtWebError(error));
75 }
76
77 static void qt_wk_didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
78 {
79     if (!WKFrameIsMainFrame(frame))
80         return;
81
82     toQtWebPageProxy(clientInfo)->updateNavigationState();
83     toQtWebPageProxy(clientInfo)->loadDidBegin();
84 }
85
86 static void qt_wk_didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
87 {
88     dispatchLoadFailed(frame, clientInfo, error);
89 }
90
91 static void qt_wk_didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
92 {
93     if (!WKFrameIsMainFrame(frame))
94         return;
95     WebFrameProxy* wkframe = toImpl(frame);
96     QString urlStr(wkframe->url());
97     QUrl qUrl = urlStr;
98     toQtWebPageProxy(clientInfo)->updateNavigationState();
99     toQtWebPageProxy(clientInfo)->didChangeUrl(qUrl);
100     toQtWebPageProxy(clientInfo)->loadDidCommit();
101 }
102
103 static void qt_wk_didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
104 {
105     dispatchLoadSucceeded(frame, clientInfo);
106 }
107
108 static void qt_wk_didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
109 {
110     dispatchLoadFailed(frame, clientInfo, error);
111 }
112
113 static void qt_wk_didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void* clientInfo)
114 {
115     WebFrameProxy* wkframe = toImpl(frame);
116     QString urlStr(wkframe->url());
117     QUrl qUrl = urlStr;
118     toQtWebPageProxy(clientInfo)->updateNavigationState();
119     toQtWebPageProxy(clientInfo)->didChangeUrl(qUrl);
120 }
121
122 static void qt_wk_didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
123 {
124     if (!WKFrameIsMainFrame(frame))
125         return;
126     QString qTitle = WKStringCopyQString(title);
127     toQtWebPageProxy(clientInfo)->didChangeTitle(qTitle);
128 }
129
130 static void qt_wk_didStartProgress(WKPageRef page, const void* clientInfo)
131 {
132     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(0);
133 }
134
135 static void qt_wk_didChangeProgress(WKPageRef page, const void* clientInfo)
136 {
137     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(WKPageGetEstimatedProgress(page) * 100);
138 }
139
140 static void qt_wk_didFinishProgress(WKPageRef page, const void* clientInfo)
141 {
142     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(100);
143 }
144
145 static void qt_wk_didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
146 {
147     if (!WKFrameIsMainFrame(frame))
148         return;
149
150     toQtWebPageProxy(clientInfo)->didFinishFirstNonEmptyLayout();
151 }
152
153 static Qt::MouseButton toQtMouseButton(WKEventMouseButton button)
154 {
155     switch (button) {
156     case kWKEventMouseButtonLeftButton:
157         return Qt::LeftButton;
158     case kWKEventMouseButtonMiddleButton:
159         return Qt::MiddleButton;
160     case kWKEventMouseButtonRightButton:
161         return Qt::RightButton;
162     }
163     return Qt::NoButton;
164 }
165
166 static Qt::KeyboardModifiers toQtKeyboardModifiers(WKEventModifiers modifiers)
167 {
168     Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
169     if (modifiers & kWKEventModifiersShiftKey)
170         qtModifiers |= Qt::ShiftModifier;
171     if (modifiers & kWKEventModifiersControlKey)
172         qtModifiers |= Qt::ControlModifier;
173     if (modifiers & kWKEventModifiersAltKey)
174         qtModifiers |= Qt::AltModifier;
175     if (modifiers & kWKEventModifiersMetaKey)
176         qtModifiers |= Qt::MetaModifier;
177     return qtModifiers;
178 }
179
180 static void qt_wk_decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
181 {
182     QtPolicyInterface* policyInterface = toQtPolicyInterface(clientInfo);
183     WKURLRef requestURL = WKURLRequestCopyURL(request);
184     QUrl qUrl = WKURLCopyQUrl(requestURL);
185     WKRelease(requestURL);
186
187     QtPolicyInterface::PolicyAction action = policyInterface->navigationPolicyForURL(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers));
188     switch (action) {
189     case QtPolicyInterface::Use:
190         WKFramePolicyListenerUse(listener);
191         break;
192     case QtPolicyInterface::Download:
193         WKFramePolicyListenerDownload(listener);
194         break;
195     case QtPolicyInterface::Ignore:
196         WKFramePolicyListenerIgnore(listener);
197         break;
198     }
199 }
200
201 static void qt_wk_decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
202 {
203     String type = toImpl(response)->resourceResponse().mimeType();
204     type.makeLower();
205     bool canShowMIMEType = toImpl(frame)->canShowMIMEType(type);
206
207     if (WKPageGetMainFrame(page) == frame) {
208         if (canShowMIMEType) {
209             WKFramePolicyListenerUse(listener);
210             return;
211         }
212
213         // If we can't use (show) it then we should download it.
214         WKFramePolicyListenerDownload(listener);
215         return;
216     }
217
218     // 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.
219     // It makes the browser intentionally behave differently when it comes to text(application)/xml content in subframes vs. mainframe.
220     if (!canShowMIMEType && !(type == "text/xml" || type == "application/xml")) {
221         WKFramePolicyListenerIgnore(listener);
222         return;
223     }
224
225     WKFramePolicyListenerUse(listener);
226 }
227
228 void qt_wk_didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void*)
229 {
230     if (!WKStringIsEqualToUTF8CString(messageName, "MessageFromNavigatorQtObject"))
231         return;
232
233     ASSERT(messageBody);
234     ASSERT(WKGetTypeID(messageBody) == WKArrayGetTypeID());
235
236     WKArrayRef body = static_cast<WKArrayRef>(messageBody);
237     ASSERT(WKArrayGetSize(body) == 2);
238     ASSERT(WKGetTypeID(WKArrayGetItemAtIndex(body, 0)) == WKPageGetTypeID());
239     ASSERT(WKGetTypeID(WKArrayGetItemAtIndex(body, 1)) == WKStringGetTypeID());
240
241     WKPageRef page = static_cast<WKPageRef>(WKArrayGetItemAtIndex(body, 0));
242     WKStringRef str = static_cast<WKStringRef>(WKArrayGetItemAtIndex(body, 1));
243
244     toImpl(page)->didReceiveMessageFromNavigatorQtObject(toImpl(str)->string());
245 }
246
247 void setupPageLoaderClient(QtWebPageProxy* qtWebPageProxy, WebPageProxy* webPageProxy)
248 {
249     WKPageLoaderClient loadClient;
250     memset(&loadClient, 0, sizeof(WKPageLoaderClient));
251     loadClient.version = kWKPageLoaderClientCurrentVersion;
252     loadClient.clientInfo = qtWebPageProxy;
253     loadClient.didStartProvisionalLoadForFrame = qt_wk_didStartProvisionalLoadForFrame;
254     loadClient.didFailProvisionalLoadWithErrorForFrame = qt_wk_didFailProvisionalLoadWithErrorForFrame;
255     loadClient.didCommitLoadForFrame = qt_wk_didCommitLoadForFrame;
256     loadClient.didFinishLoadForFrame = qt_wk_didFinishLoadForFrame;
257     loadClient.didFailLoadWithErrorForFrame = qt_wk_didFailLoadWithErrorForFrame;
258     loadClient.didSameDocumentNavigationForFrame = qt_wk_didSameDocumentNavigationForFrame;
259     loadClient.didReceiveTitleForFrame = qt_wk_didReceiveTitleForFrame;
260     loadClient.didStartProgress = qt_wk_didStartProgress;
261     loadClient.didChangeProgress = qt_wk_didChangeProgress;
262     loadClient.didFinishProgress = qt_wk_didFinishProgress;
263     loadClient.didFirstVisuallyNonEmptyLayoutForFrame = qt_wk_didFirstVisuallyNonEmptyLayoutForFrame;
264     WKPageSetPageLoaderClient(qtWebPageProxy->pageRef(), &loadClient);
265 }
266
267 void setupPagePolicyClient(QtPolicyInterface* policyInterface, WebPageProxy* webPageProxy)
268 {
269     WKPagePolicyClient policyClient;
270     memset(&policyClient, 0, sizeof(WKPagePolicyClient));
271     policyClient.version = kWKPagePolicyClientCurrentVersion;
272     policyClient.clientInfo = policyInterface;
273     policyClient.decidePolicyForNavigationAction = qt_wk_decidePolicyForNavigationAction;
274     policyClient.decidePolicyForResponse = qt_wk_decidePolicyForResponse;
275     WKPageSetPagePolicyClient(toAPI(webPageProxy), &policyClient);
276 }
277
278 void setupContextInjectedBundleClient(WKContextRef context)
279 {
280     WKContextInjectedBundleClient injectedBundleClient;
281     memset(&injectedBundleClient, 0, sizeof(WKContextInjectedBundleClient));
282     injectedBundleClient.version = kWKContextInjectedBundleClientCurrentVersion;
283     injectedBundleClient.didReceiveMessageFromInjectedBundle = qt_wk_didReceiveMessageFromInjectedBundle;
284     WKContextSetInjectedBundleClient(context, &injectedBundleClient);
285 }