b4b0771657747057999b194a85c440202ad950f2
[WebKit.git] / Source / WebKit2 / UIProcess / qt / QtWebPageProxy.cpp
1 /*
2  * Copyright (C) 2010, 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 "QtWebPageProxy.h"
23
24 #include "QtWebError.h"
25 #include "qwebpreferences_p.h"
26
27 #include "ClientImpl.h"
28 #include "qwkhistory.h"
29 #include "qwkhistory_p.h"
30 #include "FindIndicator.h"
31 #include "LocalizedStrings.h"
32 #include "NativeWebKeyboardEvent.h"
33 #include "NotImplemented.h"
34 #include "QtPolicyInterface.h"
35 #include "QtViewInterface.h"
36 #include "QtWebUndoCommand.h"
37 #include "WebBackForwardList.h"
38 #include "WebContext.h"
39 #include "WebContextMenuProxyQt.h"
40 #include "WebEditCommandProxy.h"
41 #include "WebEventFactoryQt.h"
42 #include "WebPopupMenuProxyQt.h"
43 #include "WKStringQt.h"
44 #include "WKURLQt.h"
45 #include <QApplication>
46 #include <QGraphicsSceneMouseEvent>
47 #include <QJSEngine>
48 #include <QMimeData>
49 #include <QTouchEvent>
50 #include <QUndoStack>
51 #include <QtDebug>
52 #include <WebCore/Cursor.h>
53 #include <WebCore/DragData.h>
54 #include <WebCore/FloatRect.h>
55 #include <WebCore/NotImplemented.h>
56 #include <WebKit2/WKFrame.h>
57 #include <WebKit2/WKPageGroup.h>
58 #include <WebKit2/WKRetainPtr.h>
59
60 using namespace WebKit;
61 using namespace WebCore;
62
63
64 RefPtr<WebContext> QtWebPageProxy::s_defaultContext;
65
66 unsigned QtWebPageProxy::s_defaultPageProxyCount = 0;
67
68 PassRefPtr<WebContext> QtWebPageProxy::defaultWKContext()
69 {
70     if (!s_defaultContext)
71         s_defaultContext = WebContext::create(String());
72     return s_defaultContext;
73 }
74
75 static inline Qt::DropActions dragOperationToDropActions(unsigned dragOperations)
76 {
77     Qt::DropActions result = Qt::IgnoreAction;
78     if (dragOperations & DragOperationCopy)
79         result |= Qt::CopyAction;
80     if (dragOperations & DragOperationMove)
81         result |= Qt::MoveAction;
82     if (dragOperations & DragOperationGeneric)
83         result |= Qt::MoveAction;
84     if (dragOperations & DragOperationLink)
85         result |= Qt::LinkAction;
86     return result;
87 }
88
89 WebCore::DragOperation dropActionToDragOperation(Qt::DropActions actions)
90 {
91     unsigned result = 0;
92     if (actions & Qt::CopyAction)
93         result |= DragOperationCopy;
94     if (actions & Qt::MoveAction)
95         result |= (DragOperationMove | DragOperationGeneric);
96     if (actions & Qt::LinkAction)
97         result |= DragOperationLink;
98     if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
99         result = DragOperationEvery;
100     return (DragOperation)result;
101 }
102
103 QtWebPageProxy::QtWebPageProxy(QtViewInterface* viewInterface, QtPolicyInterface* policyInterface, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
104     : m_viewInterface(viewInterface)
105     , m_policyInterface(policyInterface)
106     , m_context(contextRef ? toImpl(contextRef) : defaultWKContext())
107     , m_preferences(0)
108     , m_undoStack(adoptPtr(new QUndoStack(this)))
109     , m_loadProgress(0)
110 {
111     ASSERT(viewInterface);
112     m_webPageProxy = m_context->createWebPage(this, toImpl(pageGroupRef));
113     m_history = QWKHistoryPrivate::createHistory(this, m_webPageProxy->backForwardList());
114     if (!contextRef)
115         s_defaultPageProxyCount++;
116 }
117
118 void QtWebPageProxy::init()
119 {
120     m_webPageProxy->initializeWebPage();
121
122     WKPageLoaderClient loadClient;
123     memset(&loadClient, 0, sizeof(WKPageLoaderClient));
124     loadClient.version = kWKPageLoaderClientCurrentVersion;
125     loadClient.clientInfo = this;
126     loadClient.didStartProvisionalLoadForFrame = qt_wk_didStartProvisionalLoadForFrame;
127     loadClient.didFailProvisionalLoadWithErrorForFrame = qt_wk_didFailProvisionalLoadWithErrorForFrame;
128     loadClient.didCommitLoadForFrame = qt_wk_didCommitLoadForFrame;
129     loadClient.didFinishLoadForFrame = qt_wk_didFinishLoadForFrame;
130     loadClient.didFailLoadWithErrorForFrame = qt_wk_didFailLoadWithErrorForFrame;
131     loadClient.didSameDocumentNavigationForFrame = qt_wk_didSameDocumentNavigationForFrame;
132     loadClient.didReceiveTitleForFrame = qt_wk_didReceiveTitleForFrame;
133     loadClient.didStartProgress = qt_wk_didStartProgress;
134     loadClient.didChangeProgress = qt_wk_didChangeProgress;
135     loadClient.didFinishProgress = qt_wk_didFinishProgress;
136     WKPageSetPageLoaderClient(pageRef(), &loadClient);
137
138     WKPageUIClient uiClient;
139     memset(&uiClient, 0, sizeof(WKPageUIClient));
140     uiClient.version = kWKPageUIClientCurrentVersion;
141     uiClient.clientInfo = m_viewInterface;
142     uiClient.runJavaScriptAlert = qt_wk_runJavaScriptAlert;
143     uiClient.runJavaScriptConfirm = qt_wk_runJavaScriptConfirm;
144     uiClient.runJavaScriptPrompt = qt_wk_runJavaScriptPrompt;
145     uiClient.setStatusText = qt_wk_setStatusText;
146     uiClient.runOpenPanel = qt_wk_runOpenPanel;
147     uiClient.mouseDidMoveOverElement = qt_wk_mouseDidMoveOverElement;
148     WKPageSetPageUIClient(toAPI(m_webPageProxy.get()), &uiClient);
149
150     if (m_policyInterface) {
151         WKPagePolicyClient policyClient;
152         memset(&policyClient, 0, sizeof(WKPagePolicyClient));
153         policyClient.version = kWKPagePolicyClientCurrentVersion;
154         policyClient.clientInfo = m_policyInterface;
155         policyClient.decidePolicyForNavigationAction = qt_wk_decidePolicyForNavigationAction;
156         policyClient.decidePolicyForResponse = qt_wk_decidePolicyForResponse;
157         WKPageSetPagePolicyClient(toAPI(m_webPageProxy.get()), &policyClient);
158     }
159 }
160
161 QtWebPageProxy::~QtWebPageProxy()
162 {
163     m_webPageProxy->close();
164     // The context is the default one and we're deleting the last QtWebPageProxy.
165     if (m_context == s_defaultContext) {
166         ASSERT(s_defaultPageProxyCount > 0);
167         s_defaultPageProxyCount--;
168         if (!s_defaultPageProxyCount)
169             s_defaultContext.clear();
170     }
171     delete m_history;
172 }
173
174 bool QtWebPageProxy::handleEvent(QEvent* ev)
175 {
176     switch (ev->type()) {
177     case QEvent::KeyPress:
178         return handleKeyPressEvent(reinterpret_cast<QKeyEvent*>(ev));
179     case QEvent::KeyRelease:
180         return handleKeyReleaseEvent(reinterpret_cast<QKeyEvent*>(ev));
181     case QEvent::FocusIn:
182         return handleFocusInEvent(reinterpret_cast<QFocusEvent*>(ev));
183     case QEvent::FocusOut:
184         return handleFocusOutEvent(reinterpret_cast<QFocusEvent*>(ev));
185     }
186
187     // FIXME: Move all common event handling here.
188     return false;
189 }
190
191 bool QtWebPageProxy::handleKeyPressEvent(QKeyEvent* ev)
192 {
193     m_webPageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
194     return true;
195 }
196
197 bool QtWebPageProxy::handleKeyReleaseEvent(QKeyEvent* ev)
198 {
199     m_webPageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
200     return true;
201 }
202
203 bool QtWebPageProxy::handleFocusInEvent(QFocusEvent*)
204 {
205     m_webPageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
206     return true;
207 }
208
209 bool QtWebPageProxy::handleFocusOutEvent(QFocusEvent*)
210 {
211     m_webPageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
212     return true;
213 }
214
215 void QtWebPageProxy::setCursor(const WebCore::Cursor& cursor)
216 {
217     m_viewInterface->didChangeCursor(*cursor.platformCursor());
218 }
219
220 void QtWebPageProxy::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
221 {
222     notImplemented();
223 }
224
225 void QtWebPageProxy::setViewNeedsDisplay(const WebCore::IntRect& rect)
226 {
227     m_viewInterface->setViewNeedsDisplay(QRect(rect));
228 }
229
230 void QtWebPageProxy::displayView()
231 {
232     // FIXME: Implement.
233 }
234
235 void QtWebPageProxy::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
236 {
237     // FIXME: Implement.
238 }
239
240 WebCore::IntSize QtWebPageProxy::viewSize()
241 {
242     return WebCore::IntSize(m_viewInterface->drawingAreaSize());
243 }
244
245 bool QtWebPageProxy::isViewWindowActive()
246 {
247     return m_viewInterface->isActive();
248 }
249
250 bool QtWebPageProxy::isViewFocused()
251 {
252     return m_viewInterface->hasFocus();
253 }
254
255 bool QtWebPageProxy::isViewVisible()
256 {
257     return m_viewInterface->isVisible();
258 }
259
260 bool QtWebPageProxy::isViewInWindow()
261 {
262     // FIXME: Implement.
263     return true;
264 }
265
266 void QtWebPageProxy::enterAcceleratedCompositingMode(const LayerTreeContext&)
267 {
268     // FIXME: Implement.
269 }
270
271 void QtWebPageProxy::exitAcceleratedCompositingMode()
272 {
273     // FIXME: Implement.
274 }
275
276 void QtWebPageProxy::pageDidRequestScroll(const IntPoint& point)
277 {
278     emit scrollRequested(point.x(), point.y());
279 }
280
281 void QtWebPageProxy::didChangeContentsSize(const IntSize& newSize)
282 {
283     m_viewInterface->contentSizeChanged(QSize(newSize));
284 }
285
286 void QtWebPageProxy::toolTipChanged(const String&, const String& newTooltip)
287 {
288     m_viewInterface->didChangeToolTip(QString(newTooltip));
289 }
290
291 void QtWebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo)
292 {
293     if (undoOrRedo == WebPageProxy::Undo) {
294         const QtWebUndoCommand* webUndoCommand = static_cast<const QtWebUndoCommand*>(m_undoStack->command(m_undoStack->index()));
295         if (webUndoCommand && webUndoCommand->inUndoRedo())
296             return;
297         m_undoStack->push(new QtWebUndoCommand(command));
298     }
299 }
300
301 void QtWebPageProxy::clearAllEditCommands()
302 {
303     m_undoStack->clear();
304 }
305
306 bool QtWebPageProxy::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
307 {
308     if (undoOrRedo == WebPageProxy::Undo)
309         return m_undoStack->canUndo();
310     return m_undoStack->canRedo();
311 }
312
313 void QtWebPageProxy::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
314 {
315     if (undoOrRedo == WebPageProxy::Undo)
316         m_undoStack->undo();
317     else
318         m_undoStack->redo();
319 }
320
321 FloatRect QtWebPageProxy::convertToDeviceSpace(const FloatRect& rect)
322 {
323     return rect;
324 }
325
326 IntPoint QtWebPageProxy::screenToWindow(const IntPoint& point)
327 {
328     return point;
329 }
330
331 IntRect QtWebPageProxy::windowToScreen(const IntRect& rect)
332 {
333     return rect;
334 }
335
336 FloatRect QtWebPageProxy::convertToUserSpace(const FloatRect& rect)
337 {
338     return rect;
339 }
340
341 void QtWebPageProxy::selectionChanged(bool, bool, bool, bool)
342 {
343 }
344
345 void QtWebPageProxy::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
346 {
347 }
348
349 PassRefPtr<WebPopupMenuProxy> QtWebPageProxy::createPopupMenuProxy(WebPageProxy*)
350 {
351     return WebPopupMenuProxyQt::create();
352 }
353
354 PassRefPtr<WebContextMenuProxy> QtWebPageProxy::createContextMenuProxy(WebPageProxy*)
355 {
356     return WebContextMenuProxyQt::create(m_webPageProxy.get(), m_viewInterface);
357 }
358
359 void QtWebPageProxy::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut)
360 {
361 }
362
363 void QtWebPageProxy::didCommitLoadForMainFrame(bool useCustomRepresentation)
364 {
365 }
366
367 void QtWebPageProxy::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
368 {
369 }
370
371 void QtWebPageProxy::flashBackingStoreUpdates(const Vector<IntRect>&)
372 {
373     notImplemented();
374 }
375
376 WKPageRef QtWebPageProxy::pageRef() const
377 {
378     return toAPI(m_webPageProxy.get());;
379 }
380
381 void QtWebPageProxy::didFindZoomableArea(const IntPoint& target, const IntRect& area)
382 {
383     m_viewInterface->didFindZoomableArea(QPoint(target), QRect(area));
384 }
385
386 void QtWebPageProxy::didChangeUrl(const QUrl& url)
387 {
388     m_viewInterface->didChangeUrl(url);
389 }
390
391 void QtWebPageProxy::didChangeTitle(const QString& newTitle)
392 {
393     m_viewInterface->didChangeTitle(newTitle);
394 }
395
396 void QtWebPageProxy::loadDidBegin()
397 {
398     m_viewInterface->loadDidBegin();
399 }
400
401 void QtWebPageProxy::loadDidCommit()
402 {
403     m_viewInterface->loadDidCommit();
404 }
405
406 void QtWebPageProxy::loadDidSucceed()
407 {
408     m_viewInterface->loadDidSucceed();
409 }
410
411 void QtWebPageProxy::loadDidFail(const QtWebError& error)
412 {
413     m_viewInterface->loadDidFail(error);
414 }
415
416 void QtWebPageProxy::didChangeLoadProgress(int newLoadProgress)
417 {
418     m_loadProgress = newLoadProgress;
419     m_viewInterface->didChangeLoadProgress(newLoadProgress);
420 }
421
422 void QtWebPageProxy::paint(QPainter* painter, const QRect& area)
423 {
424     if (m_webPageProxy->isValid())
425         paintContent(painter, area);
426     else
427         painter->fillRect(area, Qt::white);
428 }
429
430 bool QtWebPageProxy::canGoBack() const
431 {
432     return m_webPageProxy->canGoBack();
433 }
434
435 void QtWebPageProxy::goBack()
436 {
437     m_webPageProxy->goBack();
438 }
439
440 bool QtWebPageProxy::canGoForward() const
441 {
442     return m_webPageProxy->canGoForward();
443 }
444
445 void QtWebPageProxy::goForward()
446 {
447     m_webPageProxy->goForward();
448 }
449
450 bool QtWebPageProxy::canStop() const
451 {
452     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
453     return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
454 }
455
456 void QtWebPageProxy::stop()
457 {
458     m_webPageProxy->stopLoading();
459 }
460
461 bool QtWebPageProxy::canReload() const
462 {
463     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
464     if (mainFrame)
465         return (WebFrameProxy::LoadStateFinished == mainFrame->loadState());
466     return m_webPageProxy->backForwardList()->currentItem();
467 }
468
469 void QtWebPageProxy::reload()
470 {
471     m_webPageProxy->reload(/* reloadFromOrigin */ true);
472 }
473
474 void QtWebPageProxy::navigationStateChanged()
475 {
476     emit updateNavigationState();
477 }
478
479 void QtWebPageProxy::didRelaunchProcess()
480 {
481     updateNavigationState();
482     m_viewInterface->didRelaunchProcess();
483     setDrawingAreaSize(m_viewInterface->drawingAreaSize());
484 }
485
486 void QtWebPageProxy::processDidCrash()
487 {
488     updateNavigationState();
489     m_viewInterface->processDidCrash();
490 }
491
492 QWebPreferences* QtWebPageProxy::preferences() const
493 {
494     if (!m_preferences) {
495         WKPageGroupRef pageGroupRef = WKPageGetPageGroup(pageRef());
496         m_preferences = QWebPreferencesPrivate::createPreferences(pageGroupRef);
497     }
498
499     return m_preferences;
500 }
501
502 void QtWebPageProxy::setCustomUserAgent(const QString& userAgent)
503 {
504     WKRetainPtr<WKStringRef> wkUserAgent(WKStringCreateWithQString(userAgent));
505     WKPageSetCustomUserAgent(pageRef(), wkUserAgent.get());
506 }
507
508 QString QtWebPageProxy::customUserAgent() const
509 {
510     return WKStringCopyQString(WKPageCopyCustomUserAgent(pageRef()));
511 }
512
513 void QtWebPageProxy::load(const QUrl& url)
514 {
515     WKRetainPtr<WKURLRef> wkurl(WKURLCreateWithQUrl(url));
516     WKPageLoadURL(pageRef(), wkurl.get());
517 }
518
519 QUrl QtWebPageProxy::url() const
520 {
521     WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef());
522     if (!frame)
523         return QUrl();
524     return WKURLCopyQUrl(WKFrameCopyURL(frame.get()));
525 }
526
527 QString QtWebPageProxy::title() const
528 {
529     return WKStringCopyQString(WKPageCopyTitle(toAPI(m_webPageProxy.get())));
530 }
531
532 void QtWebPageProxy::setDrawingAreaSize(const QSize& size)
533 {
534     if (!m_webPageProxy->drawingArea())
535         return;
536     m_webPageProxy->drawingArea()->setSize(IntSize(size), IntSize());
537 }
538
539 qreal QtWebPageProxy::textZoomFactor() const
540 {
541     return WKPageGetTextZoomFactor(pageRef());
542 }
543
544 void QtWebPageProxy::setTextZoomFactor(qreal zoomFactor)
545 {
546     WKPageSetTextZoomFactor(pageRef(), zoomFactor);
547 }
548
549 qreal QtWebPageProxy::pageZoomFactor() const
550 {
551     return WKPageGetPageZoomFactor(pageRef());
552 }
553
554 void QtWebPageProxy::setPageZoomFactor(qreal zoomFactor)
555 {
556     WKPageSetPageZoomFactor(pageRef(), zoomFactor);
557 }
558
559 void QtWebPageProxy::setPageAndTextZoomFactors(qreal pageZoomFactor, qreal textZoomFactor)
560 {
561     WKPageSetPageAndTextZoomFactors(pageRef(), pageZoomFactor, textZoomFactor);
562 }
563
564 QWKHistory* QtWebPageProxy::history() const
565 {
566     return m_history;
567 }
568
569 void QtWebPageProxy::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage)
570 {
571     QImage dragQImage;
572     if (dragImage)
573         dragQImage = dragImage->createQImage();
574     else if (dragData.platformData() && dragData.platformData()->hasImage())
575         dragQImage = qvariant_cast<QImage>(dragData.platformData()->imageData());
576
577
578     DragOperation dragOperationMask = dragData.draggingSourceOperationMask();
579     QMimeData* mimeData = const_cast<QMimeData*>(dragData.platformData());
580     Qt::DropActions supportedDropActions = dragOperationToDropActions(dragOperationMask);
581
582     QPoint clientPosition;
583     QPoint globalPosition;
584     Qt::DropAction actualDropAction;
585
586     m_viewInterface->startDrag(supportedDropActions, dragQImage, mimeData,
587                                &clientPosition, &globalPosition, &actualDropAction);
588
589     m_webPageProxy->dragEnded(clientPosition, globalPosition, dropActionToDragOperation(actualDropAction));
590 }
591
592 void QtWebPageProxy::didChangeViewportProperties(const WebCore::ViewportArguments& args)
593 {
594     m_viewInterface->didChangeViewportProperties(args);
595 }
596
597 #include "moc_QtWebPageProxy.cpp"