[Qt][WK2] Move the C API callback setup out of QtWebPageProxy
[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 <QtViewInterface.h>
30 #include <QtWebPageProxy.h>
31 #include <WKArray.h>
32 #include <WKFrame.h>
33 #include <WKFramePolicyListener.h>
34 #include <WKHitTestResult.h>
35 #include <WKOpenPanelParameters.h>
36 #include <WKOpenPanelResultListener.h>
37 #include <WKType.h>
38 #include <WKURLRequest.h>
39
40 using namespace WebKit;
41
42 static QtWebPageProxy* toQtWebPageProxy(const void* clientInfo)
43 {
44     if (clientInfo)
45         return reinterpret_cast<QtWebPageProxy*>(const_cast<void*>(clientInfo));
46     return 0;
47 }
48
49 static inline QtViewInterface* toQtViewInterface(const void* clientInfo)
50 {
51     ASSERT(clientInfo);
52     return reinterpret_cast<QtViewInterface*>(const_cast<void*>(clientInfo));
53 }
54
55 static inline QtPolicyInterface* toQtPolicyInterface(const void* clientInfo)
56 {
57     ASSERT(clientInfo);
58     return reinterpret_cast<QtPolicyInterface*>(const_cast<void*>(clientInfo));
59 }
60
61 static void dispatchLoadSucceeded(WKFrameRef frame, const void* clientInfo)
62 {
63     if (!WKFrameIsMainFrame(frame))
64         return;
65
66     toQtWebPageProxy(clientInfo)->updateNavigationState();
67     toQtWebPageProxy(clientInfo)->loadDidSucceed();
68 }
69
70 static void dispatchLoadFailed(WKFrameRef frame, const void* clientInfo, WKErrorRef error)
71 {
72     if (!WKFrameIsMainFrame(frame))
73         return;
74
75     toQtWebPageProxy(clientInfo)->updateNavigationState();
76
77     int errorCode = WKErrorGetErrorCode(error);
78     if (toImpl(error)->platformError().isCancellation() || errorCode == kWKErrorCodeFrameLoadInterruptedByPolicyChange || errorCode == kWKErrorCodePlugInWillHandleLoad)
79         return;
80
81     toQtWebPageProxy(clientInfo)->loadDidFail(QtWebError(error));
82 }
83
84 static void qt_wk_didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
85 {
86     if (!WKFrameIsMainFrame(frame))
87         return;
88
89     toQtWebPageProxy(clientInfo)->updateNavigationState();
90     toQtWebPageProxy(clientInfo)->loadDidBegin();
91 }
92
93 static void qt_wk_didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
94 {
95     dispatchLoadFailed(frame, clientInfo, error);
96 }
97
98 static void qt_wk_didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
99 {
100     if (!WKFrameIsMainFrame(frame))
101         return;
102     WebFrameProxy* wkframe = toImpl(frame);
103     QString urlStr(wkframe->url());
104     QUrl qUrl = urlStr;
105     toQtWebPageProxy(clientInfo)->updateNavigationState();
106     toQtWebPageProxy(clientInfo)->didChangeUrl(qUrl);
107     toQtWebPageProxy(clientInfo)->loadDidCommit();
108 }
109
110 static void qt_wk_didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
111 {
112     dispatchLoadSucceeded(frame, clientInfo);
113 }
114
115 static void qt_wk_didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
116 {
117     dispatchLoadFailed(frame, clientInfo, error);
118 }
119
120 static void qt_wk_didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void* clientInfo)
121 {
122     WebFrameProxy* wkframe = toImpl(frame);
123     QString urlStr(wkframe->url());
124     QUrl qUrl = urlStr;
125     toQtWebPageProxy(clientInfo)->updateNavigationState();
126     toQtWebPageProxy(clientInfo)->didChangeUrl(qUrl);
127 }
128
129 static void qt_wk_didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
130 {
131     if (!WKFrameIsMainFrame(frame))
132         return;
133     QString qTitle = WKStringCopyQString(title);
134     toQtWebPageProxy(clientInfo)->didChangeTitle(qTitle);
135 }
136
137 static void qt_wk_didStartProgress(WKPageRef page, const void* clientInfo)
138 {
139     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(0);
140 }
141
142 static void qt_wk_didChangeProgress(WKPageRef page, const void* clientInfo)
143 {
144     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(WKPageGetEstimatedProgress(page) * 100);
145 }
146
147 static void qt_wk_didFinishProgress(WKPageRef page, const void* clientInfo)
148 {
149     toQtWebPageProxy(clientInfo)->didChangeLoadProgress(100);
150 }
151
152 static void qt_wk_runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo)
153 {
154     QString qAlertText = WKStringCopyQString(alertText);
155     toQtViewInterface(clientInfo)->runJavaScriptAlert(qAlertText);
156 }
157
158 static bool qt_wk_runJavaScriptConfirm(WKPageRef, WKStringRef message, WKFrameRef, const void* clientInfo)
159 {
160     QString qMessage = WKStringCopyQString(message);
161     return toQtViewInterface(clientInfo)->runJavaScriptConfirm(qMessage);
162 }
163
164 static inline WKStringRef createNullWKString()
165 {
166     RefPtr<WebString> webString = WebString::createNull();
167     return toAPI(webString.release().leakRef());
168 }
169
170 static WKStringRef qt_wk_runJavaScriptPrompt(WKPageRef, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void* clientInfo)
171 {
172     QString qMessage = WKStringCopyQString(message);
173     QString qDefaultValue = WKStringCopyQString(defaultValue);
174     bool ok = false;
175     QString result = toQtViewInterface(clientInfo)->runJavaScriptPrompt(qMessage, qDefaultValue, ok);
176     if (!ok)
177         return createNullWKString();
178     return WKStringCreateWithQString(result);
179 }
180
181 static void qt_wk_setStatusText(WKPageRef, WKStringRef text, const void *clientInfo)
182 {
183     QString qText = WKStringCopyQString(text);
184     toQtViewInterface(clientInfo)->didChangeStatusText(qText);
185 }
186
187 static void qt_wk_runOpenPanel(WKPageRef, WKFrameRef, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void* clientInfo)
188 {
189     Vector<String> wkSelectedFileNames = toImpl(parameters)->selectedFileNames();
190
191     QStringList selectedFileNames;
192     if (!wkSelectedFileNames.isEmpty())
193         for (unsigned i = 0; wkSelectedFileNames.size(); ++i)
194             selectedFileNames += wkSelectedFileNames.at(i);
195
196     QtViewInterface::FileChooserType allowMultipleFiles = WKOpenPanelParametersGetAllowsMultipleFiles(parameters) ? QtViewInterface::MultipleFilesSelection : QtViewInterface::SingleFileSelection;
197     toQtViewInterface(clientInfo)->chooseFiles(listener, selectedFileNames, allowMultipleFiles);
198 }
199
200 static void qt_wk_mouseDidMoveOverElement(WKPageRef page, WKHitTestResultRef hitTestResult, WKEventModifiers modifiers, WKTypeRef userData, const void* clientInfo)
201 {
202     const QUrl absoluteLinkUrl = WKURLCopyQUrl(WKHitTestResultCopyAbsoluteLinkURL(hitTestResult));
203     const QString linkTitle = WKStringCopyQString(WKHitTestResultCopyLinkTitle(hitTestResult));
204     toQtViewInterface(clientInfo)->didMouseMoveOverElement(absoluteLinkUrl, linkTitle);
205 }
206
207 static Qt::MouseButton toQtMouseButton(WKEventMouseButton button)
208 {
209     switch (button) {
210     case kWKEventMouseButtonLeftButton:
211         return Qt::LeftButton;
212     case kWKEventMouseButtonMiddleButton:
213         return Qt::MiddleButton;
214     case kWKEventMouseButtonRightButton:
215         return Qt::RightButton;
216     }
217     return Qt::NoButton;
218 }
219
220 static Qt::KeyboardModifiers toQtKeyboardModifiers(WKEventModifiers modifiers)
221 {
222     Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
223     if (modifiers & kWKEventModifiersShiftKey)
224         qtModifiers |= Qt::ShiftModifier;
225     if (modifiers & kWKEventModifiersControlKey)
226         qtModifiers |= Qt::ControlModifier;
227     if (modifiers & kWKEventModifiersAltKey)
228         qtModifiers |= Qt::AltModifier;
229     if (modifiers & kWKEventModifiersMetaKey)
230         qtModifiers |= Qt::MetaModifier;
231     return qtModifiers;
232 }
233
234 static void qt_wk_decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
235 {
236     QtPolicyInterface* policyInterface = toQtPolicyInterface(clientInfo);
237     WKURLRef requestURL = WKURLRequestCopyURL(request);
238     QUrl qUrl = WKURLCopyQUrl(requestURL);
239     WKRelease(requestURL);
240
241     QtPolicyInterface::PolicyAction action = policyInterface->navigationPolicyForURL(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers));
242     switch (action) {
243     case QtPolicyInterface::Use:
244         WKFramePolicyListenerUse(listener);
245         break;
246     case QtPolicyInterface::Download:
247         WKFramePolicyListenerDownload(listener);
248         break;
249     case QtPolicyInterface::Ignore:
250         WKFramePolicyListenerIgnore(listener);
251         break;
252     }
253 }
254
255 static void qt_wk_decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
256 {
257     String type = toImpl(response)->resourceResponse().mimeType();
258     type.makeLower();
259     bool canShowMIMEType = toImpl(frame)->canShowMIMEType(type);
260
261     if (WKPageGetMainFrame(page) == frame) {
262         if (canShowMIMEType) {
263             WKFramePolicyListenerUse(listener);
264             return;
265         }
266
267         // If we can't use (show) it then we should download it.
268         WKFramePolicyListenerDownload(listener);
269         return;
270     }
271
272     // 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.
273     // It makes the browser intentionally behave differently when it comes to text(application)/xml content in subframes vs. mainframe.
274     if (!canShowMIMEType && !(type == "text/xml" || type == "application/xml")) {
275         WKFramePolicyListenerIgnore(listener);
276         return;
277     }
278
279     WKFramePolicyListenerUse(listener);
280 }
281
282 void setupPageLoaderClient(QtWebPageProxy* qtWebPageProxy, WebPageProxy* webPageProxy)
283 {
284     WKPageLoaderClient loadClient;
285     memset(&loadClient, 0, sizeof(WKPageLoaderClient));
286     loadClient.version = kWKPageLoaderClientCurrentVersion;
287     loadClient.clientInfo = qtWebPageProxy;
288     loadClient.didStartProvisionalLoadForFrame = qt_wk_didStartProvisionalLoadForFrame;
289     loadClient.didFailProvisionalLoadWithErrorForFrame = qt_wk_didFailProvisionalLoadWithErrorForFrame;
290     loadClient.didCommitLoadForFrame = qt_wk_didCommitLoadForFrame;
291     loadClient.didFinishLoadForFrame = qt_wk_didFinishLoadForFrame;
292     loadClient.didFailLoadWithErrorForFrame = qt_wk_didFailLoadWithErrorForFrame;
293     loadClient.didSameDocumentNavigationForFrame = qt_wk_didSameDocumentNavigationForFrame;
294     loadClient.didReceiveTitleForFrame = qt_wk_didReceiveTitleForFrame;
295     loadClient.didStartProgress = qt_wk_didStartProgress;
296     loadClient.didChangeProgress = qt_wk_didChangeProgress;
297     loadClient.didFinishProgress = qt_wk_didFinishProgress;
298     WKPageSetPageLoaderClient(qtWebPageProxy->pageRef(), &loadClient);
299 }
300
301 void setupPageUiClient(QtWebPageProxy* qtWebPageProxy, WebPageProxy* webPageProxy)
302 {
303     WKPageUIClient uiClient;
304     memset(&uiClient, 0, sizeof(WKPageUIClient));
305     uiClient.version = kWKPageUIClientCurrentVersion;
306     uiClient.clientInfo = qtWebPageProxy->viewInterface();
307     uiClient.runJavaScriptAlert = qt_wk_runJavaScriptAlert;
308     uiClient.runJavaScriptConfirm = qt_wk_runJavaScriptConfirm;
309     uiClient.runJavaScriptPrompt = qt_wk_runJavaScriptPrompt;
310     uiClient.setStatusText = qt_wk_setStatusText;
311     uiClient.runOpenPanel = qt_wk_runOpenPanel;
312     uiClient.mouseDidMoveOverElement = qt_wk_mouseDidMoveOverElement;
313     WKPageSetPageUIClient(toAPI(webPageProxy), &uiClient);
314 }
315
316 void setupPagePolicyClient(QtPolicyInterface* policyInterface, WebPageProxy* webPageProxy)
317 {
318     WKPagePolicyClient policyClient;
319     memset(&policyClient, 0, sizeof(WKPagePolicyClient));
320     policyClient.version = kWKPagePolicyClientCurrentVersion;
321     policyClient.clientInfo = policyInterface;
322     policyClient.decidePolicyForNavigationAction = qt_wk_decidePolicyForNavigationAction;
323     policyClient.decidePolicyForResponse = qt_wk_decidePolicyForResponse;
324     WKPageSetPagePolicyClient(toAPI(webPageProxy), &policyClient);
325 }