f8d9bc6f7e874a3bff5249429f4f123adc405882
[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 <qdeclarativeengine.h>
25 #include <qquickcanvas.h>
26 #include "qquickwebview_p.h"
27 #include "qquickwebview_p_p.h"
28 #include "qquickwebpage_p.h"
29 #include "QtWebError.h"
30 #include "qwebdownloaditem_p.h"
31 #include "qwebdownloaditem_p_p.h"
32 #include "qwebpreferences_p.h"
33 #include "qwebpreferences_p_p.h"
34
35 #include "ClientImpl.h"
36 #include "DownloadProxy.h"
37 #include "DrawingAreaProxyImpl.h"
38 #include "qwkhistory.h"
39 #include "qwkhistory_p.h"
40 #include "FindIndicator.h"
41 #include "LocalizedStrings.h"
42 #include "MutableArray.h"
43 #include "NativeWebKeyboardEvent.h"
44 #include "NativeWebMouseEvent.h"
45 #include "NativeWebWheelEvent.h"
46 #include "NotImplemented.h"
47 #include "QtPolicyInterface.h"
48 #include "QtViewportInteractionEngine.h"
49 #include "QtWebUndoCommand.h"
50 #include "WebBackForwardList.h"
51 #include "WebContext.h"
52 #include "WebContextMenuProxyQt.h"
53 #include "WebEditCommandProxy.h"
54 #include "WebEventFactoryQt.h"
55 #include "WebPopupMenuProxyQtDesktop.h"
56 #include "WKStringQt.h"
57 #include "WKURLQt.h"
58 #include <QDrag>
59 #include <QGuiApplication>
60 #include <QGraphicsSceneMouseEvent>
61 #include <QJSEngine>
62 #include <QMimeData>
63 #include <QStyleHints>
64 #include <QTouchEvent>
65 #include <QUndoStack>
66 #include <QtDebug>
67 #include <WebCore/Cursor.h>
68 #include <WebCore/DragData.h>
69 #include <WebCore/FloatRect.h>
70 #include <WebCore/NotImplemented.h>
71 #include <WebCore/Region.h>
72 #include <WebKit2/WKFrame.h>
73 #include <WebKit2/WKPageGroup.h>
74 #include <WebKit2/WKRetainPtr.h>
75
76 using namespace WebKit;
77 using namespace WebCore;
78
79 RefPtr<WebContext> QtWebPageProxy::s_defaultContext;
80 RefPtr<QtDownloadManager> QtWebPageProxy::s_downloadManager;
81
82 unsigned QtWebPageProxy::s_defaultPageProxyCount = 0;
83
84 PassRefPtr<WebContext> QtWebPageProxy::defaultWKContext()
85 {
86     if (!s_defaultContext) {
87         s_defaultContext = WebContext::create(String());
88         setupContextInjectedBundleClient(toAPI(s_defaultContext.get()));
89         s_downloadManager = QtDownloadManager::create(s_defaultContext.get());
90     }
91     return s_defaultContext;
92 }
93
94 static inline Qt::DropAction dragOperationToDropAction(unsigned dragOperation)
95 {
96     Qt::DropAction result = Qt::IgnoreAction;
97     if (dragOperation & DragOperationCopy)
98         result = Qt::CopyAction;
99     else if (dragOperation & DragOperationMove)
100         result = Qt::MoveAction;
101     else if (dragOperation & DragOperationGeneric)
102         result = Qt::MoveAction;
103     else if (dragOperation & DragOperationLink)
104         result = Qt::LinkAction;
105     return result;
106 }
107
108 static inline Qt::DropActions dragOperationToDropActions(unsigned dragOperations)
109 {
110     Qt::DropActions result = Qt::IgnoreAction;
111     if (dragOperations & DragOperationCopy)
112         result |= Qt::CopyAction;
113     if (dragOperations & DragOperationMove)
114         result |= Qt::MoveAction;
115     if (dragOperations & DragOperationGeneric)
116         result |= Qt::MoveAction;
117     if (dragOperations & DragOperationLink)
118         result |= Qt::LinkAction;
119     return result;
120 }
121
122 WebCore::DragOperation dropActionToDragOperation(Qt::DropActions actions)
123 {
124     unsigned result = 0;
125     if (actions & Qt::CopyAction)
126         result |= DragOperationCopy;
127     if (actions & Qt::MoveAction)
128         result |= (DragOperationMove | DragOperationGeneric);
129     if (actions & Qt::LinkAction)
130         result |= DragOperationLink;
131     if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
132         result = DragOperationEvery;
133     return (DragOperation)result;
134 }
135
136 QtWebPageProxy::QtWebPageProxy(QQuickWebPage* qmlWebPage, QQuickWebView* qmlWebView, QtViewportInteractionEngine* viewportInteractionEngine, QtPolicyInterface* policyInterface, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
137     : m_qmlWebPage(qmlWebPage)
138     , m_qmlWebView(qmlWebView)
139     , m_interactionEngine(viewportInteractionEngine)
140     , m_panGestureRecognizer(viewportInteractionEngine)
141     , m_pinchGestureRecognizer(viewportInteractionEngine)
142     , m_tapGestureRecognizer(viewportInteractionEngine, this)
143     , m_policyInterface(policyInterface)
144     , m_context(contextRef ? toImpl(contextRef) : defaultWKContext())
145     , m_undoStack(adoptPtr(new QUndoStack(this)))
146     , m_loadProgress(0)
147     , m_navigatorQtObjectEnabled(false)
148 {
149     m_webPageProxy = m_context->createWebPage(this, toImpl(pageGroupRef));
150     m_history = QWKHistoryPrivate::createHistory(this, m_webPageProxy->backForwardList());
151     if (!contextRef)
152         s_defaultPageProxyCount++;
153 }
154
155 void QtWebPageProxy::init()
156 {
157     m_webPageProxy->initializeWebPage();
158
159     setupPageLoaderClient(this, m_webPageProxy.get());
160
161     if (m_policyInterface)
162         setupPagePolicyClient(m_policyInterface, m_webPageProxy.get());
163 }
164
165 QtWebPageProxy::~QtWebPageProxy()
166 {
167     m_webPageProxy->close();
168     // The context is the default one and we're deleting the last QtWebPageProxy.
169     if (m_context == s_defaultContext) {
170         ASSERT(s_defaultPageProxyCount > 0);
171         s_defaultPageProxyCount--;
172         if (!s_defaultPageProxyCount) {
173             s_defaultContext.clear();
174             s_downloadManager.clear();
175         }
176     }
177     delete m_history;
178 }
179
180 bool QtWebPageProxy::handleEvent(QEvent* ev)
181 {
182     switch (ev->type()) {
183     case QEvent::MouseMove:
184         return handleMouseMoveEvent(reinterpret_cast<QMouseEvent*>(ev));
185     case QEvent::MouseButtonPress:
186         return handleMousePressEvent(reinterpret_cast<QMouseEvent*>(ev));
187     case QEvent::MouseButtonRelease:
188         return handleMouseReleaseEvent(reinterpret_cast<QMouseEvent*>(ev));
189     case QEvent::MouseButtonDblClick:
190         return handleMouseDoubleClickEvent(reinterpret_cast<QMouseEvent*>(ev));
191     case QEvent::Wheel:
192         return handleWheelEvent(reinterpret_cast<QWheelEvent*>(ev));
193     case QEvent::HoverLeave:
194         return handleHoverLeaveEvent(reinterpret_cast<QHoverEvent*>(ev));
195     case QEvent::HoverEnter: // Fall-through, for WebKit the distinction doesn't matter.
196     case QEvent::HoverMove:
197         return handleHoverMoveEvent(reinterpret_cast<QHoverEvent*>(ev));
198     case QEvent::DragEnter:
199         return handleDragEnterEvent(reinterpret_cast<QDragEnterEvent*>(ev));
200     case QEvent::DragLeave:
201         return handleDragLeaveEvent(reinterpret_cast<QDragLeaveEvent*>(ev));
202     case QEvent::DragMove:
203         return handleDragMoveEvent(reinterpret_cast<QDragMoveEvent*>(ev));
204     case QEvent::Drop:
205         return handleDropEvent(reinterpret_cast<QDropEvent*>(ev));
206     case QEvent::KeyPress:
207         return handleKeyPressEvent(reinterpret_cast<QKeyEvent*>(ev));
208     case QEvent::KeyRelease:
209         return handleKeyReleaseEvent(reinterpret_cast<QKeyEvent*>(ev));
210     case QEvent::FocusIn:
211         return handleFocusInEvent(reinterpret_cast<QFocusEvent*>(ev));
212     case QEvent::FocusOut:
213         return handleFocusOutEvent(reinterpret_cast<QFocusEvent*>(ev));
214     case QEvent::TouchBegin:
215     case QEvent::TouchEnd:
216     case QEvent::TouchUpdate:
217         touchEvent(static_cast<QTouchEvent*>(ev));
218         return true;
219     }
220
221     // FIXME: Move all common event handling here.
222     return false;
223 }
224
225 bool QtWebPageProxy::handleMouseMoveEvent(QMouseEvent* ev)
226 {
227     // For some reason mouse press results in mouse hover (which is
228     // converted to mouse move for WebKit). We ignore these hover
229     // events by comparing lastPos with newPos.
230     // NOTE: lastPos from the event always comes empty, so we work
231     // around that here.
232     static QPointF lastPos = QPointF();
233     if (lastPos == ev->pos())
234         return ev->isAccepted();
235     lastPos = ev->pos();
236
237     m_webPageProxy->handleMouseEvent(NativeWebMouseEvent(ev, /*eventClickCount=*/0));
238
239     return ev->isAccepted();
240 }
241
242 bool QtWebPageProxy::handleMousePressEvent(QMouseEvent* ev)
243 {
244     if (m_tripleClickTimer.isActive() && (ev->pos() - m_tripleClick).manhattanLength() < qApp->styleHints()->startDragDistance()) {
245         m_webPageProxy->handleMouseEvent(NativeWebMouseEvent(ev, /*eventClickCount=*/3));
246         return ev->isAccepted();
247     }
248
249     m_webPageProxy->handleMouseEvent(NativeWebMouseEvent(ev, /*eventClickCount=*/1));
250     return ev->isAccepted();
251 }
252
253 bool QtWebPageProxy::handleMouseReleaseEvent(QMouseEvent* ev)
254 {
255     m_webPageProxy->handleMouseEvent(NativeWebMouseEvent(ev, /*eventClickCount=*/0));
256     return ev->isAccepted();
257 }
258
259 bool QtWebPageProxy::handleMouseDoubleClickEvent(QMouseEvent* ev)
260 {
261     m_webPageProxy->handleMouseEvent(NativeWebMouseEvent(ev, /*eventClickCount=*/2));
262
263     m_tripleClickTimer.start(qApp->styleHints()->mouseDoubleClickInterval(), this);
264     m_tripleClick = ev->localPos().toPoint();
265     return ev->isAccepted();
266 }
267
268 bool QtWebPageProxy::handleWheelEvent(QWheelEvent* ev)
269 {
270     m_webPageProxy->handleWheelEvent(NativeWebWheelEvent(ev));
271     // FIXME: Handle whether the page used the wheel event or not.
272     if (m_interactionEngine)
273         m_interactionEngine->wheelEvent(ev);
274     return ev->isAccepted();
275 }
276
277 bool QtWebPageProxy::handleHoverLeaveEvent(QHoverEvent* ev)
278 {
279     // To get the correct behavior of mouseout, we need to turn the Leave event of our webview into a mouse move
280     // to a very far region.
281     QHoverEvent fakeEvent(QEvent::HoverMove, QPoint(INT_MIN, INT_MIN), ev->oldPos());
282     return handleHoverMoveEvent(&fakeEvent);
283 }
284
285 bool QtWebPageProxy::handleHoverMoveEvent(QHoverEvent* ev)
286 {
287     QMouseEvent me(QEvent::MouseMove, ev->pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
288     me.setAccepted(ev->isAccepted());
289
290     return handleMouseMoveEvent(&me);
291 }
292
293 bool QtWebPageProxy::handleDragEnterEvent(QDragEnterEvent* ev)
294 {
295     m_webPageProxy->resetDragOperation();
296     // FIXME: Should not use QCursor::pos()
297     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), dropActionToDragOperation(ev->possibleActions()));
298     m_webPageProxy->dragEntered(&dragData);
299     ev->acceptProposedAction();
300     return true;
301 }
302
303 bool QtWebPageProxy::handleDragLeaveEvent(QDragLeaveEvent* ev)
304 {
305     bool accepted = ev->isAccepted();
306
307     // FIXME: Should not use QCursor::pos()
308     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
309     m_webPageProxy->dragExited(&dragData);
310     m_webPageProxy->resetDragOperation();
311
312     ev->setAccepted(accepted);
313     return accepted;
314 }
315
316 bool QtWebPageProxy::handleDragMoveEvent(QDragMoveEvent* ev)
317 {
318     bool accepted = ev->isAccepted();
319
320     // FIXME: Should not use QCursor::pos()
321     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), dropActionToDragOperation(ev->possibleActions()));
322     m_webPageProxy->dragUpdated(&dragData);
323     ev->setDropAction(dragOperationToDropAction(m_webPageProxy->dragSession().operation));
324     if (m_webPageProxy->dragSession().operation != DragOperationNone)
325         ev->accept();
326
327     ev->setAccepted(accepted);
328     return accepted;
329 }
330
331 bool QtWebPageProxy::handleDropEvent(QDropEvent* ev)
332 {
333     bool accepted = ev->isAccepted();
334
335     // FIXME: Should not use QCursor::pos()
336     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), dropActionToDragOperation(ev->possibleActions()));
337     SandboxExtension::Handle handle;
338     m_webPageProxy->performDrag(&dragData, String(), handle);
339     ev->setDropAction(dragOperationToDropAction(m_webPageProxy->dragSession().operation));
340     ev->accept();
341
342     ev->setAccepted(accepted);
343     return accepted;
344 }
345
346 void QtWebPageProxy::handleSingleTapEvent(const QTouchEvent::TouchPoint& point)
347 {
348     WebGestureEvent gesture(WebEvent::GestureSingleTap, point.pos().toPoint(), point.screenPos().toPoint(), WebEvent::Modifiers(0), 0);
349     m_webPageProxy->handleGestureEvent(gesture);
350 }
351
352 void QtWebPageProxy::handleDoubleTapEvent(const QTouchEvent::TouchPoint& point)
353 {
354     m_webPageProxy->findZoomableAreaForPoint(point.pos().toPoint());
355 }
356
357 void QtWebPageProxy::showContextMenu(QSharedPointer<QMenu> menu)
358 {
359     // Remove the active menu in case this function is called twice.
360     if (activeMenu)
361         activeMenu->hide();
362
363     if (menu->isEmpty())
364         return;
365
366     QWindow* window = m_qmlWebView->canvas();
367     if (!window)
368         return;
369
370     activeMenu = menu;
371
372     activeMenu->window()->winId(); // Ensure that the menu has a window
373     Q_ASSERT(activeMenu->window()->windowHandle());
374     activeMenu->window()->windowHandle()->setTransientParent(window);
375
376     QPoint menuPositionInScene = m_qmlWebView->mapToScene(menu->pos()).toPoint();
377     menu->exec(window->mapToGlobal(menuPositionInScene));
378     // The last function to get out of exec() clear the local copy.
379     if (activeMenu == menu)
380         activeMenu.clear();
381 }
382
383 void QtWebPageProxy::hideContextMenu()
384 {
385     if (activeMenu)
386         activeMenu->hide();
387 }
388
389 void QtWebPageProxy::timerEvent(QTimerEvent* ev)
390 {
391     int timerId = ev->timerId();
392     if (timerId == m_tripleClickTimer.timerId())
393         m_tripleClickTimer.stop();
394     else
395         QObject::timerEvent(ev);
396 }
397
398 bool QtWebPageProxy::handleKeyPressEvent(QKeyEvent* ev)
399 {
400     m_webPageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
401     return true;
402 }
403
404 bool QtWebPageProxy::handleKeyReleaseEvent(QKeyEvent* ev)
405 {
406     m_webPageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
407     return true;
408 }
409
410 bool QtWebPageProxy::handleFocusInEvent(QFocusEvent*)
411 {
412     m_webPageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
413     return true;
414 }
415
416 bool QtWebPageProxy::handleFocusOutEvent(QFocusEvent*)
417 {
418     m_webPageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
419     return true;
420 }
421
422 void QtWebPageProxy::setCursor(const WebCore::Cursor& cursor)
423 {
424     // FIXME: This is a temporary fix until we get cursor support in QML items.
425     QGuiApplication::setOverrideCursor(*cursor.platformCursor());
426 }
427
428 void QtWebPageProxy::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
429 {
430     notImplemented();
431 }
432
433 void QtWebPageProxy::setViewNeedsDisplay(const WebCore::IntRect&)
434 {
435     m_qmlWebPage->update();
436 }
437
438 void QtWebPageProxy::displayView()
439 {
440     // FIXME: Implement.
441 }
442
443 void QtWebPageProxy::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
444 {
445     // FIXME: Implement.
446 }
447
448 WebCore::IntSize QtWebPageProxy::viewSize()
449 {
450     return WebCore::IntSize(m_qmlWebPage->width(), m_qmlWebPage->height());
451 }
452
453 bool QtWebPageProxy::isViewWindowActive()
454 {
455     // FIXME: The scene graph does not have the concept of being active or not when this was written.
456     return true;
457 }
458
459 bool QtWebPageProxy::isViewFocused()
460 {
461     return m_qmlWebView->hasFocus();
462 }
463
464 bool QtWebPageProxy::isViewVisible()
465 {
466     return m_qmlWebView->isVisible() && m_qmlWebPage->isVisible();
467 }
468
469 bool QtWebPageProxy::isViewInWindow()
470 {
471     // FIXME: Implement.
472     return true;
473 }
474
475 void QtWebPageProxy::enterAcceleratedCompositingMode(const LayerTreeContext&)
476 {
477     // FIXME: Implement.
478 }
479
480 void QtWebPageProxy::exitAcceleratedCompositingMode()
481 {
482     // FIXME: Implement.
483 }
484
485 void QtWebPageProxy::pageDidRequestScroll(const IntPoint& pos)
486 {
487     m_qmlWebView->d_func()->scrollPositionRequested(pos);
488 }
489
490 void QtWebPageProxy::didFinishFirstNonEmptyLayout()
491 {
492     m_qmlWebView->d_func()->didFinishFirstNonEmptyLayout();
493 }
494
495 void QtWebPageProxy::didChangeContentsSize(const IntSize& newSize)
496 {
497     m_qmlWebView->d_func()->didChangeContentsSize(newSize);
498 }
499
500 void QtWebPageProxy::didChangeViewportProperties(const WebCore::ViewportArguments& args)
501 {
502     m_qmlWebView->d_func()->didChangeViewportProperties(args);
503 }
504
505 void QtWebPageProxy::toolTipChanged(const String&, const String& newTooltip)
506 {
507     // There is not yet any UI defined for the tooltips for mobile so we ignore the change.
508 }
509
510 void QtWebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo)
511 {
512     if (undoOrRedo == WebPageProxy::Undo) {
513         const QtWebUndoCommand* webUndoCommand = static_cast<const QtWebUndoCommand*>(m_undoStack->command(m_undoStack->index()));
514         if (webUndoCommand && webUndoCommand->inUndoRedo())
515             return;
516         m_undoStack->push(new QtWebUndoCommand(command));
517     }
518 }
519
520 void QtWebPageProxy::clearAllEditCommands()
521 {
522     m_undoStack->clear();
523 }
524
525 bool QtWebPageProxy::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
526 {
527     if (undoOrRedo == WebPageProxy::Undo)
528         return m_undoStack->canUndo();
529     return m_undoStack->canRedo();
530 }
531
532 void QtWebPageProxy::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
533 {
534     if (undoOrRedo == WebPageProxy::Undo)
535         m_undoStack->undo();
536     else
537         m_undoStack->redo();
538 }
539
540 FloatRect QtWebPageProxy::convertToDeviceSpace(const FloatRect& rect)
541 {
542     return rect;
543 }
544
545 IntPoint QtWebPageProxy::screenToWindow(const IntPoint& point)
546 {
547     return point;
548 }
549
550 IntRect QtWebPageProxy::windowToScreen(const IntRect& rect)
551 {
552     return rect;
553 }
554
555 FloatRect QtWebPageProxy::convertToUserSpace(const FloatRect& rect)
556 {
557     return rect;
558 }
559
560 void QtWebPageProxy::selectionChanged(bool, bool, bool, bool)
561 {
562 }
563
564 void QtWebPageProxy::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
565 {
566 }
567
568 PassRefPtr<WebPopupMenuProxy> QtWebPageProxy::createPopupMenuProxy(WebPageProxy*)
569 {
570     return WebPopupMenuProxyQtDesktop::create(m_webPageProxy.get(), m_qmlWebView);
571 }
572
573 PassRefPtr<WebContextMenuProxy> QtWebPageProxy::createContextMenuProxy(WebPageProxy*)
574 {
575     return WebContextMenuProxyQt::create(this);
576 }
577
578 void QtWebPageProxy::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate)
579 {
580 }
581
582 void QtWebPageProxy::didCommitLoadForMainFrame(bool useCustomRepresentation)
583 {
584 }
585
586 void QtWebPageProxy::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
587 {
588 }
589
590 void QtWebPageProxy::flashBackingStoreUpdates(const Vector<IntRect>&)
591 {
592     notImplemented();
593 }
594
595 WKPageRef QtWebPageProxy::pageRef() const
596 {
597     return toAPI(m_webPageProxy.get());;
598 }
599
600 void QtWebPageProxy::didFindZoomableArea(const IntPoint& target, const IntRect& area)
601 {
602     if (!m_interactionEngine)
603         return;
604
605     // FIXME: As the find method might not respond immediately during load etc,
606     // we should ignore all but the latest request.
607     m_interactionEngine->zoomToAreaGestureEnded(QPointF(target), QRectF(area));
608 }
609
610 void QtWebPageProxy::didReceiveMessageFromNavigatorQtObject(const String& message)
611 {
612     QVariantMap variantMap;
613     variantMap.insert(QLatin1String("data"), QString(message));
614     variantMap.insert(QLatin1String("origin"), url());
615     emit receivedMessageFromNavigatorQtObject(variantMap);
616 }
617
618 void QtWebPageProxy::didChangeUrl(const QUrl& url)
619 {
620     emit m_qmlWebView->urlChanged(url);
621 }
622
623 void QtWebPageProxy::didChangeTitle(const QString& newTitle)
624 {
625     emit m_qmlWebView->titleChanged(newTitle);
626 }
627
628 void QtWebPageProxy::loadDidBegin()
629 {
630     emit m_qmlWebView->loadStarted();
631 }
632
633 void QtWebPageProxy::loadDidCommit()
634 {
635     m_qmlWebView->d_func()->loadDidCommit();
636 }
637
638 void QtWebPageProxy::loadDidSucceed()
639 {
640     emit m_qmlWebView->loadSucceeded();
641 }
642
643 void QtWebPageProxy::loadDidFail(const QtWebError& error)
644 {
645     emit m_qmlWebView->loadFailed(static_cast<QQuickWebView::ErrorType>(error.type()), error.errorCode(), error.url());
646 }
647
648 void QtWebPageProxy::didChangeLoadProgress(int percentageLoaded)
649 {
650     m_loadProgress = percentageLoaded;
651     emit m_qmlWebView->loadProgressChanged(percentageLoaded);
652 }
653
654 bool QtWebPageProxy::canGoBack() const
655 {
656     return m_webPageProxy->canGoBack();
657 }
658
659 void QtWebPageProxy::goBack()
660 {
661     m_webPageProxy->goBack();
662 }
663
664 bool QtWebPageProxy::canGoForward() const
665 {
666     return m_webPageProxy->canGoForward();
667 }
668
669 void QtWebPageProxy::goForward()
670 {
671     m_webPageProxy->goForward();
672 }
673
674 bool QtWebPageProxy::canStop() const
675 {
676     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
677     return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
678 }
679
680 void QtWebPageProxy::stop()
681 {
682     m_webPageProxy->stopLoading();
683 }
684
685 bool QtWebPageProxy::canReload() const
686 {
687     RefPtr<WebKit::WebFrameProxy> mainFrame = m_webPageProxy->mainFrame();
688     if (mainFrame)
689         return (WebFrameProxy::LoadStateFinished == mainFrame->loadState());
690     return m_webPageProxy->backForwardList()->currentItem();
691 }
692
693 void QtWebPageProxy::reload()
694 {
695     m_webPageProxy->reload(/* reloadFromOrigin */ true);
696 }
697
698 void QtWebPageProxy::navigationStateChanged()
699 {
700     emit updateNavigationState();
701 }
702
703 void QtWebPageProxy::didRelaunchProcess()
704 {
705     updateNavigationState();
706     qWarning("WARNING: The web process has been successfully restarted.");
707     setDrawingAreaSize(viewSize());
708 }
709
710 void QtWebPageProxy::processDidCrash()
711 {
712     updateNavigationState();
713     m_panGestureRecognizer.reset();
714     m_pinchGestureRecognizer.reset();
715     m_tapGestureRecognizer.reset();
716
717     WebCore::KURL url(WebCore::ParsedURLString, m_webPageProxy->urlAtProcessExit());
718     qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(QUrl(url).toString(QUrl::RemoveUserInfo)));
719 }
720
721 QWebPreferences* QtWebPageProxy::preferences() const
722 {
723     if (!m_preferences)
724         m_preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(const_cast<QtWebPageProxy*>(this)));
725     return m_preferences.get();
726 }
727
728 void QtWebPageProxy::setCustomUserAgent(const QString& userAgent)
729 {
730     WKRetainPtr<WKStringRef> wkUserAgent(WKStringCreateWithQString(userAgent));
731     WKPageSetCustomUserAgent(pageRef(), wkUserAgent.get());
732 }
733
734 QString QtWebPageProxy::customUserAgent() const
735 {
736     return WKStringCopyQString(WKPageCopyCustomUserAgent(pageRef()));
737 }
738
739 void QtWebPageProxy::setNavigatorQtObjectEnabled(bool enabled)
740 {
741     static String messageName("SetNavigatorQtObjectEnabled");
742
743     ASSERT(enabled != m_navigatorQtObjectEnabled);
744     // FIXME: Currently we have to keep this information in both processes and the setting is asynchronous.
745     m_navigatorQtObjectEnabled = enabled;
746     RefPtr<MutableArray> body = MutableArray::create();
747     body->append(m_webPageProxy.get());
748     RefPtr<WebBoolean> webEnabled = WebBoolean::create(enabled);
749     body->append(webEnabled.get());
750     m_context->postMessageToInjectedBundle(messageName, body.get());
751 }
752
753 void QtWebPageProxy::setViewportInteractionEngine(QtViewportInteractionEngine* engine)
754 {
755     m_interactionEngine = engine;
756     m_panGestureRecognizer.setViewportInteractionEngine(engine);
757     m_pinchGestureRecognizer.setViewportInteractionEngine(engine);
758     m_tapGestureRecognizer.setViewportInteractionEngine(engine);
759 }
760
761 void QtWebPageProxy::postMessageToNavigatorQtObject(const QString& message)
762 {
763     static String messageName("MessageToNavigatorQtObject");
764
765     RefPtr<MutableArray> body = MutableArray::create();
766     body->append(m_webPageProxy.get());
767     RefPtr<WebString> contents = WebString::create(String(message));
768     body->append(contents.get());
769     m_context->postMessageToInjectedBundle(messageName, body.get());
770 }
771
772 void QtWebPageProxy::loadHTMLString(const QString& html, const QUrl& baseUrl)
773 {
774     WKRetainPtr<WKURLRef> wkUrl(WKURLCreateWithQUrl(baseUrl));
775     WKRetainPtr<WKStringRef> wkHtmlString(WKStringCreateWithQString(html));
776
777     WKPageLoadHTMLString(pageRef(), wkHtmlString.get(), wkUrl.get());
778 }
779
780 void QtWebPageProxy::load(const QUrl& url)
781 {
782     WKRetainPtr<WKURLRef> wkurl(WKURLCreateWithQUrl(url));
783     WKPageLoadURL(pageRef(), wkurl.get());
784 }
785
786 QUrl QtWebPageProxy::url() const
787 {
788     WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef());
789     if (!frame)
790         return QUrl();
791     return WKURLCopyQUrl(WKFrameCopyURL(frame.get()));
792 }
793
794 QString QtWebPageProxy::title() const
795 {
796     return WKStringCopyQString(WKPageCopyTitle(toAPI(m_webPageProxy.get())));
797 }
798
799 void QtWebPageProxy::setDrawingAreaSize(const QSize& size)
800 {
801     if (!m_webPageProxy->drawingArea())
802         return;
803
804     m_webPageProxy->drawingArea()->setSize(IntSize(size), IntSize());
805 }
806
807 qreal QtWebPageProxy::textZoomFactor() const
808 {
809     return WKPageGetTextZoomFactor(pageRef());
810 }
811
812 void QtWebPageProxy::setTextZoomFactor(qreal zoomFactor)
813 {
814     WKPageSetTextZoomFactor(pageRef(), zoomFactor);
815 }
816
817 qreal QtWebPageProxy::pageZoomFactor() const
818 {
819     return WKPageGetPageZoomFactor(pageRef());
820 }
821
822 void QtWebPageProxy::setPageZoomFactor(qreal zoomFactor)
823 {
824     WKPageSetPageZoomFactor(pageRef(), zoomFactor);
825 }
826
827 void QtWebPageProxy::setPageAndTextZoomFactors(qreal pageZoomFactor, qreal textZoomFactor)
828 {
829     WKPageSetPageAndTextZoomFactors(pageRef(), pageZoomFactor, textZoomFactor);
830 }
831
832 QWKHistory* QtWebPageProxy::history() const
833 {
834     return m_history;
835 }
836
837 void QtWebPageProxy::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage)
838 {
839     QImage dragQImage;
840     if (dragImage)
841         dragQImage = dragImage->createQImage();
842     else if (dragData.platformData() && dragData.platformData()->hasImage())
843         dragQImage = qvariant_cast<QImage>(dragData.platformData()->imageData());
844
845
846     DragOperation dragOperationMask = dragData.draggingSourceOperationMask();
847     QMimeData* mimeData = const_cast<QMimeData*>(dragData.platformData());
848     Qt::DropActions supportedDropActions = dragOperationToDropActions(dragOperationMask);
849
850     QPoint clientPosition;
851     QPoint globalPosition;
852     Qt::DropAction actualDropAction = Qt::IgnoreAction;
853
854     if (QWindow* window = m_qmlWebView->canvas()) {
855         QDrag* drag = new QDrag(window);
856         drag->setPixmap(QPixmap::fromImage(dragQImage));
857         drag->setMimeData(mimeData);
858         actualDropAction = drag->exec(supportedDropActions);
859         globalPosition = QCursor::pos();
860         clientPosition = window->mapFromGlobal(globalPosition);
861     }
862
863     m_webPageProxy->dragEnded(clientPosition, globalPosition, dropActionToDragOperation(actualDropAction));
864 }
865
866 void QtWebPageProxy::handleDownloadRequest(DownloadProxy* download)
867 {
868     // This function is responsible for hooking up a DownloadProxy to our API layer
869     // by creating a QWebDownloadItem. It will then wait for the QWebDownloadItem to be
870     // ready (filled with the ResourceResponse information) so we can pass it through to
871     // our WebViews.
872     QWebDownloadItem* downloadItem = new QWebDownloadItem();
873     downloadItem->d->downloadProxy = download;
874
875     connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), this, SLOT(didReceiveDownloadResponse(QWebDownloadItem*)));
876     s_downloadManager->addDownload(download, downloadItem);
877 }
878
879 void QtWebPageProxy::didReceiveDownloadResponse(QWebDownloadItem* downloadItem)
880 {
881     // Now that our downloadItem has everything we need we can emit downloadRequested.
882     if (!downloadItem)
883         return;
884
885     QDeclarativeEngine::setObjectOwnership(downloadItem, QDeclarativeEngine::JavaScriptOwnership);
886     emit m_qmlWebView->downloadRequested(downloadItem);
887 }
888
889 PassOwnPtr<DrawingAreaProxy> QtWebPageProxy::createDrawingAreaProxy()
890 {
891     return DrawingAreaProxyImpl::create(m_webPageProxy.get());
892 }
893
894 void QtWebPageProxy::renderToCurrentGLContext(const TransformationMatrix& transform, float opacity)
895 {
896     DrawingAreaProxy* drawingArea = m_webPageProxy->drawingArea();
897     if (drawingArea)
898         drawingArea->paintToCurrentGLContext(transform, opacity);
899 }
900
901 #if ENABLE(TOUCH_EVENTS)
902 void QtWebPageProxy::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled)
903 {
904     if (!m_interactionEngine)
905         return;
906
907     if (wasEventHandled || event.type() == WebEvent::TouchCancel) {
908         m_panGestureRecognizer.reset();
909         m_pinchGestureRecognizer.reset();
910         m_tapGestureRecognizer.reset();
911         return;
912     }
913
914     const QTouchEvent* ev = event.nativeEvent();
915
916     switch (ev->type()) {
917     case QEvent::TouchBegin:
918         ASSERT(!m_interactionEngine->panGestureActive());
919         ASSERT(!m_interactionEngine->pinchGestureActive());
920
921         // The interaction engine might still be animating kinetic scrolling or a scale animation
922         // such as double-tap to zoom or the bounce back effect. A touch stops the kinetic scrolling
923         // where as it does not stop the scale animation.
924         if (m_interactionEngine->scrollAnimationActive())
925             m_interactionEngine->interruptScrollAnimation();
926         break;
927     case QEvent::TouchUpdate:
928         // The scale animation can only be interrupted by a pinch gesture, which will then take over.
929         if (m_interactionEngine->scaleAnimationActive() && m_pinchGestureRecognizer.isRecognized())
930             m_interactionEngine->interruptScaleAnimation();
931         break;
932     default:
933         break;
934     }
935
936     // If the scale animation is active we don't pass the event to the recognizers. In the future
937     // we would want to queue the event here and repost then when the animation ends.
938     if (m_interactionEngine->scaleAnimationActive())
939         return;
940
941     // Convert the event timestamp from second to millisecond.
942     qint64 eventTimestampMillis = static_cast<qint64>(event.timestamp() * 1000);
943     m_panGestureRecognizer.recognize(ev, eventTimestampMillis);
944     m_pinchGestureRecognizer.recognize(ev);
945
946     if (m_panGestureRecognizer.isRecognized() || m_pinchGestureRecognizer.isRecognized())
947         m_tapGestureRecognizer.reset();
948     else {
949         const QTouchEvent* ev = event.nativeEvent();
950         m_tapGestureRecognizer.recognize(ev, eventTimestampMillis);
951     }
952 }
953 #endif
954
955 void QtWebPageProxy::setVisibleContentRectAndScale(const QRectF& visibleContentRect, float scale)
956 {
957     if (!m_webPageProxy->drawingArea())
958         return;
959
960     QRect alignedVisibleContentRect = visibleContentRect.toAlignedRect();
961     m_webPageProxy->drawingArea()->setVisibleContentsRectAndScale(alignedVisibleContentRect, scale);
962
963     // FIXME: Once we support suspend and resume, this should be delayed until the page is active if the page is suspended.
964     m_webPageProxy->setFixedVisibleContentRect(alignedVisibleContentRect);
965 }
966
967 void QtWebPageProxy::setVisibleContentRectTrajectoryVector(const QPointF& trajectoryVector)
968 {
969     if (!m_webPageProxy->drawingArea())
970         return;
971
972     m_webPageProxy->drawingArea()->setVisibleContentRectTrajectoryVector(trajectoryVector);
973 }
974
975 void QtWebPageProxy::touchEvent(QTouchEvent* event)
976 {
977 #if ENABLE(TOUCH_EVENTS)
978     m_webPageProxy->handleTouchEvent(NativeWebTouchEvent(event));
979     event->accept();
980 #else
981     ASSERT_NOT_REACHED();
982     ev->ignore();
983 #endif
984 }
985
986 void QtWebPageProxy::findZoomableAreaForPoint(const QPoint& point)
987 {
988     m_webPageProxy->findZoomableAreaForPoint(point);
989 }
990
991 #include "moc_QtWebPageProxy.cpp"