[Qt][WK2] Move non-api classes to WebKit namespace at WebKit2/UiProcess/qt
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / qt / qquickwebview.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 "qquickwebview_p.h"
23
24 #include "DownloadProxy.h"
25 #include "DrawingAreaProxyImpl.h"
26 #include "QtDialogRunner.h"
27 #include "QtDownloadManager.h"
28 #include "QtViewportInteractionEngine.h"
29 #include "QtWebContext.h"
30 #include "QtWebIconDatabaseClient.h"
31 #include "QtWebPageEventHandler.h"
32 #include "QtWebPageLoadClient.h"
33 #include "QtWebPagePolicyClient.h"
34 #include "UtilsQt.h"
35 #include "WebBackForwardList.h"
36 #include "WebPageGroup.h"
37 #include "WebPreferences.h"
38
39 #include "qquicknetworkreply_p.h"
40 #include "qquicknetworkrequest_p.h"
41 #include "qquickwebpage_p_p.h"
42 #include "qquickwebview_p_p.h"
43 #include "qwebdownloaditem_p_p.h"
44 #include "qwebloadrequest_p.h"
45 #include "qwebnavigationhistory_p.h"
46 #include "qwebnavigationhistory_p_p.h"
47 #include "qwebpreferences_p.h"
48 #include "qwebpreferences_p_p.h"
49 #include "qwebviewportinfo_p.h"
50
51 #include <JavaScriptCore/InitializeThreading.h>
52 #include <QtQml/QQmlEngine>
53 #include <QtQuick/QQuickCanvas>
54 #include <WebCore/IntPoint.h>
55 #include <WebCore/IntRect.h>
56 #include <WKOpenPanelResultListener.h>
57 #include <wtf/Assertions.h>
58 #include <wtf/MainThread.h>
59 #include <wtf/text/WTFString.h>
60
61 using namespace WebCore;
62 using namespace WebKit;
63
64 static bool s_flickableViewportEnabled = true;
65
66 static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject)
67 {
68     if (s_flickableViewportEnabled)
69         return new QQuickWebViewFlickablePrivate(publicObject);
70     return new QQuickWebViewLegacyPrivate(publicObject);
71 }
72
73 QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
74     : q_ptr(viewport)
75     , alertDialog(0)
76     , confirmDialog(0)
77     , promptDialog(0)
78     , authenticationDialog(0)
79     , certificateVerificationDialog(0)
80     , itemSelector(0)
81     , proxyAuthenticationDialog(0)
82     , filePicker(0)
83     , databaseQuotaDialog(0)
84     , m_useDefaultContentItemSize(true)
85     , m_navigatorQtObjectEnabled(false)
86     , m_renderToOffscreenBuffer(false)
87     , m_loadStartedSignalSent(false)
88     , m_dialogActive(false)
89 {
90     viewport->setClip(true);
91     viewport->setPixelAligned(true);
92     QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged()));
93     QObject::connect(viewport, SIGNAL(urlChanged()), viewport, SLOT(_q_onUrlChanged()));
94     pageView.reset(new QQuickWebPage(viewport));
95 }
96
97 QQuickWebViewPrivate::~QQuickWebViewPrivate()
98 {
99     webPageProxy->close();
100 }
101
102 // Note: we delay this initialization to make sure that QQuickWebView has its d-ptr in-place.
103 void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
104 {
105     RefPtr<WebPageGroup> pageGroup;
106     if (pageGroupRef)
107         pageGroup = toImpl(pageGroupRef);
108     else
109         pageGroup = WebPageGroup::create();
110
111     context = contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext();
112     webPageProxy = context->createWebPage(&pageClient, pageGroup.get());
113
114     QQuickWebPagePrivate* const pageViewPrivate = pageView.data()->d;
115     pageViewPrivate->initialize(webPageProxy.get());
116
117     pageLoadClient.reset(new QtWebPageLoadClient(toAPI(webPageProxy.get()), q_ptr));
118     pagePolicyClient.reset(new QtWebPagePolicyClient(toAPI(webPageProxy.get()), q_ptr));
119     pageUIClient.reset(new QtWebPageUIClient(toAPI(webPageProxy.get()), q_ptr));
120     navigationHistory = adoptPtr(QWebNavigationHistoryPrivate::createHistory(toAPI(webPageProxy.get())));
121
122     QtWebIconDatabaseClient* iconDatabase = context->iconDatabase();
123     QObject::connect(iconDatabase, SIGNAL(iconChangedForPageURL(QUrl, QUrl)), q_ptr, SLOT(_q_onIconChangedForPageURL(QUrl, QUrl)));
124
125     // Any page setting should preferrable be set before creating the page.
126     webPageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true);
127     webPageProxy->pageGroup()->preferences()->setForceCompositingMode(true);
128     webPageProxy->pageGroup()->preferences()->setFrameFlatteningEnabled(true);
129
130     pageClient.initialize(q_ptr, pageViewPrivate->eventHandler.data(), &undoController);
131     webPageProxy->initializeWebPage();
132 }
133
134 void QQuickWebViewPrivate::setTransparentBackground(bool enable)
135 {
136     webPageProxy->setDrawsTransparentBackground(enable);
137 }
138
139 bool QQuickWebViewPrivate::transparentBackground() const
140 {
141     return webPageProxy->drawsTransparentBackground();
142 }
143
144 QPointF QQuickWebViewPrivate::pageItemPos()
145 {
146     ASSERT(pageView);
147     return pageView->pos();
148 }
149
150 void QQuickWebViewPrivate::loadDidSucceed()
151 {
152     Q_Q(QQuickWebView);
153     ASSERT(!q->loading());
154     QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadSucceededStatus);
155     emit q->loadingChanged(&loadRequest);
156 }
157
158 void QQuickWebViewPrivate::onComponentComplete()
159 {
160     if (m_deferedUrlToLoad.isEmpty())
161         return;
162
163     q_ptr->setUrl(m_deferedUrlToLoad);
164 }
165
166 void QQuickWebViewPrivate::setNeedsDisplay()
167 {
168     Q_Q(QQuickWebView);
169     if (renderToOffscreenBuffer()) {
170         // TODO: we can maintain a real image here and use it for pixel tests. Right now this is used only for running the rendering code-path while running tests.
171         QImage dummyImage(1, 1, QImage::Format_ARGB32);
172         QPainter painter(&dummyImage);
173         q->page()->d->paint(&painter);
174         return;
175     }
176
177     q->page()->update();
178 }
179
180 void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QUrl& pageURL, const QUrl& iconURL)
181 {
182     Q_Q(QQuickWebView);
183     if (q->url() != pageURL)
184         return;
185
186     setIcon(iconURL);
187 }
188
189 void QQuickWebViewPrivate::didChangeLoadingState(QWebLoadRequest* loadRequest)
190 {
191     Q_Q(QQuickWebView);
192     ASSERT(q->loading() == (loadRequest->status() == QQuickWebView::LoadStartedStatus));
193     emit q->loadingChanged(loadRequest);
194     m_loadStartedSignalSent = loadRequest->status() == QQuickWebView::LoadStartedStatus;
195 }
196
197 void QQuickWebViewPrivate::didChangeBackForwardList()
198 {
199     navigationHistory->d->reset();
200 }
201
202 void QQuickWebViewPrivate::processDidCrash()
203 {
204     pageView->eventHandler()->resetGestureRecognizers();
205     QUrl url(KURL(WebCore::ParsedURLString, webPageProxy->urlAtProcessExit()));
206     if (m_loadStartedSignalSent) {
207         QWebLoadRequest loadRequest(url, QQuickWebView::LoadFailedStatus, QLatin1String("The web process crashed."), QQuickWebView::InternalErrorDomain, 0);
208         didChangeLoadingState(&loadRequest);
209     }
210     qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(url.toString(QUrl::RemoveUserInfo)));
211 }
212
213 void QQuickWebViewPrivate::didRelaunchProcess()
214 {
215     qWarning("WARNING: The web process has been successfully restarted.");
216
217     webPageProxy->drawingArea()->setSize(viewSize(), IntSize());
218     updateViewportSize();
219 }
220
221 PassOwnPtr<DrawingAreaProxy> QQuickWebViewPrivate::createDrawingAreaProxy()
222 {
223     return DrawingAreaProxyImpl::create(webPageProxy.get());
224 }
225
226 void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download)
227 {
228     Q_Q(QQuickWebView);
229     // This function is responsible for hooking up a DownloadProxy to our API layer
230     // by creating a QWebDownloadItem. It will then wait for the QWebDownloadItem to be
231     // ready (filled with the ResourceResponse information) so we can pass it through to
232     // our WebViews.
233     QWebDownloadItem* downloadItem = new QWebDownloadItem();
234     downloadItem->d->downloadProxy = download;
235
236     q->connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), q, SLOT(_q_onReceivedResponseFromDownload(QWebDownloadItem*)));
237     context->downloadManager()->addDownload(download, downloadItem);
238 }
239
240 void QQuickWebViewPrivate::_q_onVisibleChanged()
241 {
242     webPageProxy->viewStateDidChange(WebPageProxy::ViewIsVisible);
243 }
244
245 void QQuickWebViewPrivate::_q_onUrlChanged()
246 {
247     Q_Q(QQuickWebView);
248     context->iconDatabase()->requestIconForPageURL(q->url());
249 }
250
251 void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* downloadItem)
252 {
253     // Now that our downloadItem has everything we need we can emit downloadRequested.
254     if (!downloadItem)
255         return;
256
257     Q_Q(QQuickWebView);
258     QDeclarativeEngine::setObjectOwnership(downloadItem, QDeclarativeEngine::JavaScriptOwnership);
259     emit q->experimental()->downloadRequested(downloadItem);
260 }
261
262 void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText)
263 {
264     if (!alertDialog)
265         return;
266
267     Q_Q(QQuickWebView);
268     QtDialogRunner dialogRunner;
269     if (!dialogRunner.initForAlert(alertDialog, q, alertText))
270         return;
271
272     execDialogRunner(dialogRunner);
273 }
274
275 bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message)
276 {
277     if (!confirmDialog)
278         return true;
279
280     Q_Q(QQuickWebView);
281     QtDialogRunner dialogRunner;
282     if (!dialogRunner.initForConfirm(confirmDialog, q, message))
283         return true;
284
285     execDialogRunner(dialogRunner);
286
287     return dialogRunner.wasAccepted();
288 }
289
290 QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok)
291 {
292     if (!promptDialog) {
293         ok = true;
294         return defaultValue;
295     }
296
297     Q_Q(QQuickWebView);
298     QtDialogRunner dialogRunner;
299     if (!dialogRunner.initForPrompt(promptDialog, q, message, defaultValue)) {
300         ok = true;
301         return defaultValue;
302     }
303
304     execDialogRunner(dialogRunner);
305
306     ok = dialogRunner.wasAccepted();
307     return dialogRunner.result();
308 }
309
310 void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password)
311 {
312     if (!authenticationDialog)
313         return;
314
315     Q_Q(QQuickWebView);
316     QtDialogRunner dialogRunner;
317     if (!dialogRunner.initForAuthentication(authenticationDialog, q, hostname, realm, prefilledUsername))
318         return;
319
320     execDialogRunner(dialogRunner);
321
322     username = dialogRunner.username();
323     password = dialogRunner.password();
324 }
325
326 void QQuickWebViewPrivate::handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password)
327 {
328     if (!proxyAuthenticationDialog)
329         return;
330
331     Q_Q(QQuickWebView);
332     QtDialogRunner dialogRunner;
333     if (!dialogRunner.initForProxyAuthentication(proxyAuthenticationDialog, q, hostname, port, prefilledUsername))
334         return;
335
336     execDialogRunner(dialogRunner);
337
338     username = dialogRunner.username();
339     password = dialogRunner.password();
340 }
341
342 bool QQuickWebViewPrivate::handleCertificateVerificationRequest(const QString& hostname)
343 {
344     if (!certificateVerificationDialog)
345         return false;
346
347     Q_Q(QQuickWebView);
348     QtDialogRunner dialogRunner;
349     if (!dialogRunner.initForCertificateVerification(certificateVerificationDialog, q, hostname))
350         return false;
351
352     execDialogRunner(dialogRunner);
353
354     return dialogRunner.wasAccepted();
355 }
356
357 void QQuickWebViewPrivate::execDialogRunner(QtDialogRunner& dialogRunner)
358 {
359     setViewInAttachedProperties(dialogRunner.dialog());
360
361     disableMouseEvents();
362     m_dialogActive = true;
363
364     dialogRunner.exec();
365     m_dialogActive = false;
366     enableMouseEvents();
367 }
368
369 void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type)
370 {
371     Q_Q(QQuickWebView);
372
373     if (!filePicker)
374         return;
375
376     QtDialogRunner dialogRunner;
377     if (!dialogRunner.initForFilePicker(filePicker, q, selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection)))
378         return;
379
380     execDialogRunner(dialogRunner);
381
382     if (dialogRunner.wasAccepted()) {
383         QStringList selectedPaths = dialogRunner.filePaths();
384
385         Vector<RefPtr<APIObject> > wkFiles(selectedPaths.size());
386         for (unsigned i = 0; i < selectedPaths.size(); ++i)
387             wkFiles[i] = WebURL::create(QUrl::fromLocalFile(selectedPaths.at(i)).toString());            
388
389         WKOpenPanelResultListenerChooseFiles(listenerRef, toAPI(ImmutableArray::adopt(wkFiles).leakRef()));
390     } else
391         WKOpenPanelResultListenerCancel(listenerRef);
392
393 }
394
395 quint64 QQuickWebViewPrivate::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage)
396 {
397     if (!databaseQuotaDialog)
398         return 0;
399
400     Q_Q(QQuickWebView);
401     QtDialogRunner dialogRunner;
402     if (!dialogRunner.initForDatabaseQuotaDialog(databaseQuotaDialog, q, databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage))
403         return 0;
404
405     execDialogRunner(dialogRunner);
406
407     return dialogRunner.wasAccepted() ? dialogRunner.databaseQuota() : 0;
408 }
409
410 void QQuickWebViewPrivate::setViewInAttachedProperties(QObject* object)
411 {
412     Q_Q(QQuickWebView);
413     QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object));
414     attached->setView(q);
415 }
416
417 void QQuickWebViewPrivate::setIcon(const QUrl& iconURL)
418 {
419     Q_Q(QQuickWebView);
420     if (m_iconURL == iconURL)
421         return;
422
423     String oldPageURL = QUrl::fromPercentEncoding(m_iconURL.encodedFragment());
424     String newPageURL = webPageProxy->mainFrame()->url();
425
426     if (oldPageURL != newPageURL) {
427         QtWebIconDatabaseClient* iconDatabase = context->iconDatabase();
428         if (!oldPageURL.isEmpty())
429             iconDatabase->releaseIconForPageURL(oldPageURL);
430
431         if (!newPageURL.isEmpty())
432             iconDatabase->retainIconForPageURL(newPageURL);
433     }
434
435     m_iconURL = iconURL;
436     emit q->iconChanged();
437 }
438
439 bool QQuickWebViewPrivate::navigatorQtObjectEnabled() const
440 {
441     return m_navigatorQtObjectEnabled;
442 }
443
444 void QQuickWebViewPrivate::setNavigatorQtObjectEnabled(bool enabled)
445 {
446     ASSERT(enabled != m_navigatorQtObjectEnabled);
447     // FIXME: Currently we have to keep this information in both processes and the setting is asynchronous.
448     m_navigatorQtObjectEnabled = enabled;
449     context->setNavigatorQtObjectEnabled(webPageProxy.get(), enabled);
450 }
451
452 QPointF QQuickWebViewPrivate::contentPos() const
453 {
454     Q_Q(const QQuickWebView);
455     return QPointF(q->contentX(), q->contentY());
456 }
457
458 void QQuickWebViewPrivate::setContentPos(const QPointF& pos)
459 {
460     Q_Q(QQuickWebView);
461     q->setContentX(pos.x());
462     q->setContentY(pos.y());
463 }
464
465 QRect QQuickWebViewPrivate::visibleContentsRect() const
466 {
467     Q_Q(const QQuickWebView);
468     const QRectF visibleRect(q->boundingRect().intersected(pageView->boundingRect()));
469
470     return q->mapRectToWebContent(visibleRect).toAlignedRect();
471 }
472
473 WebCore::IntSize QQuickWebViewPrivate::viewSize() const
474 {
475     return WebCore::IntSize(pageView->width(), pageView->height());
476 }
477
478 void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message)
479 {
480     QVariantMap variantMap;
481     variantMap.insert(QLatin1String("data"), QString(message));
482     variantMap.insert(QLatin1String("origin"), q_ptr->url());
483     emit q_ptr->experimental()->messageReceived(variantMap);
484 }
485
486 QQuickWebViewLegacyPrivate::QQuickWebViewLegacyPrivate(QQuickWebView* viewport)
487     : QQuickWebViewPrivate(viewport)
488 {
489     // Default values for the Legacy view.
490     attributes.devicePixelRatio = 1;
491     attributes.initialScale = 1;
492     attributes.minimumScale = 1;
493     attributes.maximumScale = 1;
494     attributes.userScalable = 0;
495 }
496
497 void QQuickWebViewLegacyPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
498 {
499     QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
500     enableMouseEvents();
501
502     // Trigger setting of correct visibility flags after everything was allocated and initialized.
503     _q_onVisibleChanged();
504 }
505
506 void QQuickWebViewLegacyPrivate::updateViewportSize()
507 {
508     Q_Q(QQuickWebView);
509     QSize viewportSize = q->boundingRect().size().toSize();
510     pageView->setContentsSize(viewportSize);
511     // The fixed layout is handled by the FrameView and the drawing area doesn't behave differently
512     // whether its fixed or not. We still need to tell the drawing area which part of it
513     // has to be rendered on tiles, and in desktop mode it's all of it.
514     webPageProxy->drawingArea()->setSize(viewportSize, IntSize());
515     webPageProxy->drawingArea()->setVisibleContentsRect(IntRect(IntPoint(), viewportSize), 1, FloatPoint());
516 }
517
518 void QQuickWebViewLegacyPrivate::enableMouseEvents()
519 {
520     Q_Q(QQuickWebView);
521     q->setAcceptedMouseButtons(Qt::MouseButtonMask);
522     q->setAcceptHoverEvents(true);
523 }
524
525 void QQuickWebViewLegacyPrivate::disableMouseEvents()
526 {
527     Q_Q(QQuickWebView);
528     q->setAcceptedMouseButtons(Qt::NoButton);
529     q->setAcceptHoverEvents(false);
530 }
531
532 QQuickWebViewFlickablePrivate::QQuickWebViewFlickablePrivate(QQuickWebView* viewport)
533     : QQuickWebViewPrivate(viewport)
534     , pageIsSuspended(true)
535     , loadSuccessDispatchIsPending(false)
536 {
537     // Disable mouse events on the flickable web view so we do not
538     // select text during pan gestures on platforms which send both
539     // touch and mouse events simultaneously.
540     // FIXME: Temporary workaround code which should be removed when
541     // bug http://codereview.qt-project.org/21896 is fixed.
542     viewport->setAcceptedMouseButtons(Qt::NoButton);
543     viewport->setAcceptHoverEvents(false);
544 }
545
546 QQuickWebViewFlickablePrivate::~QQuickWebViewFlickablePrivate()
547 {
548     interactionEngine->disconnect();
549 }
550
551 void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
552 {
553     QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
554     webPageProxy->setUseFixedLayout(true);
555 }
556
557 QPointF QQuickWebViewFlickablePrivate::pageItemPos()
558 {
559     Q_Q(QQuickWebView);
560     // Flickable moves its contentItem so we need to take that position into account,
561     // as well as the potential displacement of the page on the contentItem because
562     // of additional QML items.
563     qreal xPos = q->contentItem()->x() + pageView->x();
564     qreal yPos = q->contentItem()->y() + pageView->y();
565     return QPointF(xPos, yPos);
566 }
567
568 void QQuickWebViewFlickablePrivate::updateContentsSize(const QSizeF& size)
569 {
570     Q_Q(QQuickWebView);
571
572     // Make sure that the contentItem is sized to the page
573     // if the user did not add other flickable items in QML.
574     // If the user adds items in QML he has to make sure to
575     // disable the default content item size property on the WebView
576     // and bind the contentWidth and contentHeight accordingly.
577     // This is in accordance with normal QML Flickable behaviour.
578     if (!m_useDefaultContentItemSize)
579         return;
580
581     q->setContentWidth(size.width());
582     q->setContentHeight(size.height());
583 }
584
585 void QQuickWebViewFlickablePrivate::onComponentComplete()
586 {
587     Q_Q(QQuickWebView);
588
589     interactionEngine.reset(new QtViewportInteractionEngine(q, pageView.data()));
590     pageView->eventHandler()->setViewportInteractionEngine(interactionEngine.data());
591
592     QObject::connect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), q, SLOT(_q_suspend()));
593     QObject::connect(interactionEngine.data(), SIGNAL(contentResumeRequested()), q, SLOT(_q_resume()));
594     QObject::connect(interactionEngine.data(), SIGNAL(contentViewportChanged(QPointF)), q, SLOT(_q_contentViewportChanged(QPointF)));
595
596     _q_resume();
597
598     if (loadSuccessDispatchIsPending) {
599         QQuickWebViewPrivate::loadDidSucceed();
600         loadSuccessDispatchIsPending = false;
601     }
602
603     // Trigger setting of correct visibility flags after everything was allocated and initialized.
604     _q_onVisibleChanged();
605
606     QQuickWebViewPrivate::onComponentComplete();
607 }
608
609 void QQuickWebViewFlickablePrivate::loadDidSucceed()
610 {
611     if (interactionEngine)
612         QQuickWebViewPrivate::loadDidSucceed();
613     else
614         loadSuccessDispatchIsPending = true;
615
616 }
617
618 void QQuickWebViewFlickablePrivate::loadDidCommit()
619 {
620     // Due to entering provisional load before committing, we
621     // might actually be suspended here.
622 }
623
624 void QQuickWebViewFlickablePrivate::didFinishFirstNonEmptyLayout()
625 {
626 }
627
628 void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& newAttributes)
629 {
630     Q_Q(QQuickWebView);
631
632     QSize viewportSize = q->boundingRect().size().toSize();
633
634     // FIXME: Revise these when implementing fit-to-width.
635     WebCore::ViewportAttributes attr = newAttributes;
636     WebCore::restrictMinimumScaleFactorToViewportSize(attr, viewportSize);
637     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attr);
638
639     // FIXME: Resetting here can reset more than needed. For instance it will end deferrers.
640     // This needs to be revised at some point.
641     interactionEngine->reset();
642
643     interactionEngine->setContentToDevicePixelRatio(attr.devicePixelRatio);
644
645     interactionEngine->setAllowsUserScaling(!!attr.userScalable);
646     interactionEngine->setCSSScaleBounds(attr.minimumScale, attr.maximumScale);
647
648     if (!interactionEngine->hadUserInteraction() && !pageIsSuspended)
649         interactionEngine->setCSSScale(attr.initialScale);
650
651     this->attributes = attr;
652     q->experimental()->viewportInfo()->didUpdateViewportConstraints();
653
654     // If the web app successively changes the viewport on purpose
655     // it wants to be in control and we should disable animations.
656     interactionEngine->ensureContentWithinViewportBoundary(/*immediate*/ true);
657 }
658
659 void QQuickWebViewFlickablePrivate::updateViewportSize()
660 {
661     Q_Q(QQuickWebView);
662     QSize viewportSize = q->boundingRect().size().toSize();
663
664     if (viewportSize.isEmpty() || !interactionEngine)
665         return;
666
667     WebPreferences* wkPrefs = webPageProxy->pageGroup()->preferences();
668
669     // FIXME: Remove later; Hardcode a value for now to make sure the DPI adjustment is being tested.
670     wkPrefs->setDeviceDPI(160);
671
672     wkPrefs->setDeviceWidth(viewportSize.width());
673     wkPrefs->setDeviceHeight(viewportSize.height());
674
675     // Let the WebProcess know about the new viewport size, so that
676     // it can resize the content accordingly.
677     webPageProxy->setViewportSize(viewportSize);
678
679     _q_contentViewportChanged(QPointF());
680 }
681
682 void QQuickWebViewFlickablePrivate::_q_contentViewportChanged(const QPointF& trajectoryVector)
683 {
684     Q_Q(QQuickWebView);
685     // This is only for our QML ViewportInfo debugging API.
686     q->experimental()->viewportInfo()->didUpdateCurrentScale();
687
688     DrawingAreaProxy* drawingArea = webPageProxy->drawingArea();
689     if (!drawingArea)
690         return;
691
692     const QRect visibleRect(visibleContentsRect());
693     float scale = pageView->contentsScale();
694
695     drawingArea->setVisibleContentsRect(visibleRect, scale, trajectoryVector);
696 }
697
698 void QQuickWebViewFlickablePrivate::_q_suspend()
699 {
700     pageIsSuspended = true;
701     webPageProxy->suspendActiveDOMObjectsAndAnimations();
702 }
703
704 void QQuickWebViewFlickablePrivate::_q_resume()
705 {
706     if (!interactionEngine)
707         return;
708
709     pageIsSuspended = false;
710     webPageProxy->resumeActiveDOMObjectsAndAnimations();
711
712     _q_contentViewportChanged(QPointF());
713 }
714
715 void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos)
716 {
717     interactionEngine->pagePositionRequest(pos);
718 }
719
720 void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize)
721 {
722     Q_Q(QQuickWebView);
723     pageView->setContentsSize(newSize);
724     q->experimental()->viewportInfo()->didUpdateContentsSize();
725 }
726
727 /*!
728     \qmlsignal WebView::onNavigationRequested(request)
729
730     This signal is emitted for every navigation request. The request object contains url, button and modifiers properties
731     describing the navigation action, e.g. "a middle click with shift key pressed to 'http://qt-project.org'".
732
733     The navigation will be accepted by default. To change that, one can set the action property to WebView.IgnoreRequest to reject
734     the request or WebView.DownloadRequest to trigger a download instead of navigating to the url.
735
736     The request object cannot be used after the signal handler function ends.
737 */
738
739 QQuickWebViewAttached::QQuickWebViewAttached(QObject* object)
740     : QObject(object)
741     , m_view(0)
742 {
743
744 }
745
746 void QQuickWebViewAttached::setView(QQuickWebView* view)
747 {
748     if (m_view == view)
749         return;
750     m_view = view;
751     emit viewChanged();
752 }
753
754 QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView)
755     : QObject(webView)
756     , q_ptr(webView)
757     , d_ptr(webView->d_ptr.data())
758     , schemeParent(new QObject(this))
759     , m_viewportInfo(new QWebViewportInfo(webView->d_ptr.data(), this))
760 {
761 }
762
763 QQuickWebViewExperimental::~QQuickWebViewExperimental()
764 {
765 }
766
767 void QQuickWebViewExperimental::setRenderToOffscreenBuffer(bool enable)
768 {
769     Q_D(QQuickWebView);
770     d->setRenderToOffscreenBuffer(enable);
771 }
772
773 bool QQuickWebViewExperimental::renderToOffscreenBuffer() const
774 {
775     Q_D(const QQuickWebView);
776     return d->renderToOffscreenBuffer();
777 }
778
779 bool QQuickWebViewExperimental::transparentBackground() const
780 {
781     Q_D(const QQuickWebView);
782     return d->transparentBackground();
783 }
784 void QQuickWebViewExperimental::setTransparentBackground(bool enable)
785 {
786     Q_D(QQuickWebView);
787     d->setTransparentBackground(enable);
788 }
789
790 bool QQuickWebViewExperimental::useDefaultContentItemSize() const
791 {
792     Q_D(const QQuickWebView);
793     return d->m_useDefaultContentItemSize;
794 }
795
796 void QQuickWebViewExperimental::setUseDefaultContentItemSize(bool enable)
797 {
798     Q_D(QQuickWebView);
799     d->m_useDefaultContentItemSize = enable;
800 }
801
802 void QQuickWebViewExperimental::setFlickableViewportEnabled(bool enable)
803 {
804     s_flickableViewportEnabled = enable;
805 }
806
807 bool QQuickWebViewExperimental::flickableViewportEnabled()
808 {
809     return s_flickableViewportEnabled;
810 }
811
812 void QQuickWebViewExperimental::postMessage(const QString& message)
813 {
814     Q_D(QQuickWebView);
815     d->context->postMessageToNavigatorQtObject(d->webPageProxy.get(), message);
816 }
817
818 QDeclarativeComponent* QQuickWebViewExperimental::alertDialog() const
819 {
820     Q_D(const QQuickWebView);
821     return d->alertDialog;
822 }
823
824 void QQuickWebViewExperimental::setAlertDialog(QDeclarativeComponent* alertDialog)
825 {
826     Q_D(QQuickWebView);
827     if (d->alertDialog == alertDialog)
828         return;
829     d->alertDialog = alertDialog;
830     emit alertDialogChanged();
831 }
832
833 QDeclarativeComponent* QQuickWebViewExperimental::confirmDialog() const
834 {
835     Q_D(const QQuickWebView);
836     return d->confirmDialog;
837 }
838
839 void QQuickWebViewExperimental::setConfirmDialog(QDeclarativeComponent* confirmDialog)
840 {
841     Q_D(QQuickWebView);
842     if (d->confirmDialog == confirmDialog)
843         return;
844     d->confirmDialog = confirmDialog;
845     emit confirmDialogChanged();
846 }
847
848 QWebNavigationHistory* QQuickWebViewExperimental::navigationHistory() const
849 {
850     return d_ptr->navigationHistory.get();
851 }
852
853 QDeclarativeComponent* QQuickWebViewExperimental::promptDialog() const
854 {
855     Q_D(const QQuickWebView);
856     return d->promptDialog;
857 }
858
859 QWebPreferences* QQuickWebViewExperimental::preferences() const
860 {
861     QQuickWebViewPrivate* const d = d_ptr;
862     if (!d->preferences)
863         d->preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(d));
864     return d->preferences.get();
865 }
866
867 void QQuickWebViewExperimental::setPromptDialog(QDeclarativeComponent* promptDialog)
868 {
869     Q_D(QQuickWebView);
870     if (d->promptDialog == promptDialog)
871         return;
872     d->promptDialog = promptDialog;
873     emit promptDialogChanged();
874 }
875
876 QDeclarativeComponent* QQuickWebViewExperimental::authenticationDialog() const
877 {
878     Q_D(const QQuickWebView);
879     return d->authenticationDialog;
880 }
881
882 void QQuickWebViewExperimental::setAuthenticationDialog(QDeclarativeComponent* authenticationDialog)
883 {
884     Q_D(QQuickWebView);
885     if (d->authenticationDialog == authenticationDialog)
886         return;
887     d->authenticationDialog = authenticationDialog;
888     emit authenticationDialogChanged();
889 }
890
891 QDeclarativeComponent* QQuickWebViewExperimental::proxyAuthenticationDialog() const
892 {
893     Q_D(const QQuickWebView);
894     return d->proxyAuthenticationDialog;
895 }
896
897 void QQuickWebViewExperimental::setProxyAuthenticationDialog(QDeclarativeComponent* proxyAuthenticationDialog)
898 {
899     Q_D(QQuickWebView);
900     if (d->proxyAuthenticationDialog == proxyAuthenticationDialog)
901         return;
902     d->proxyAuthenticationDialog = proxyAuthenticationDialog;
903     emit proxyAuthenticationDialogChanged();
904 }
905 QDeclarativeComponent* QQuickWebViewExperimental::certificateVerificationDialog() const
906 {
907     Q_D(const QQuickWebView);
908     return d->certificateVerificationDialog;
909 }
910
911 void QQuickWebViewExperimental::setCertificateVerificationDialog(QDeclarativeComponent* certificateVerificationDialog)
912 {
913     Q_D(QQuickWebView);
914     if (d->certificateVerificationDialog == certificateVerificationDialog)
915         return;
916     d->certificateVerificationDialog = certificateVerificationDialog;
917     emit certificateVerificationDialogChanged();
918 }
919
920 QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const
921 {
922     Q_D(const QQuickWebView);
923     return d->itemSelector;
924 }
925
926 void QQuickWebViewExperimental::setItemSelector(QDeclarativeComponent* itemSelector)
927 {
928     Q_D(QQuickWebView);
929     if (d->itemSelector == itemSelector)
930         return;
931     d->itemSelector = itemSelector;
932     emit itemSelectorChanged();
933 }
934
935 QDeclarativeComponent* QQuickWebViewExperimental::filePicker() const
936 {
937     Q_D(const QQuickWebView);
938     return d->filePicker;
939 }
940
941 void QQuickWebViewExperimental::setFilePicker(QDeclarativeComponent* filePicker)
942 {
943     Q_D(QQuickWebView);
944     if (d->filePicker == filePicker)
945         return;
946     d->filePicker = filePicker;
947     emit filePickerChanged();
948 }
949
950 QDeclarativeComponent* QQuickWebViewExperimental::databaseQuotaDialog() const
951 {
952     Q_D(const QQuickWebView);
953     return d->databaseQuotaDialog;
954 }
955
956 void QQuickWebViewExperimental::setDatabaseQuotaDialog(QDeclarativeComponent* databaseQuotaDialog)
957 {
958     Q_D(QQuickWebView);
959     if (d->databaseQuotaDialog == databaseQuotaDialog)
960         return;
961     d->databaseQuotaDialog = databaseQuotaDialog;
962     emit databaseQuotaDialogChanged();
963 }
964
965 QString QQuickWebViewExperimental::userAgent() const
966 {
967     Q_D(const QQuickWebView);
968     return d->webPageProxy->userAgent();
969 }
970
971 void QQuickWebViewExperimental::setUserAgent(const QString& userAgent)
972 {
973     Q_D(QQuickWebView);
974     if (userAgent == QString(d->webPageProxy->userAgent()))
975         return;
976
977     d->webPageProxy->setUserAgent(userAgent);
978     emit userAgentChanged();
979 }
980
981 QQuickUrlSchemeDelegate* QQuickWebViewExperimental::schemeDelegates_At(QDeclarativeListProperty<QQuickUrlSchemeDelegate>* property, int index)
982 {
983     const QObjectList children = property->object->children();
984     if (index < children.count())
985         return static_cast<QQuickUrlSchemeDelegate*>(children.at(index));
986     return 0;
987 }
988
989 void QQuickWebViewExperimental::schemeDelegates_Append(QDeclarativeListProperty<QQuickUrlSchemeDelegate>* property, QQuickUrlSchemeDelegate *scheme)
990 {
991     QObject* schemeParent = property->object;
992     scheme->setParent(schemeParent);
993     QQuickWebViewExperimental* webViewExperimental = qobject_cast<QQuickWebViewExperimental*>(property->object->parent());
994     if (!webViewExperimental)
995         return;
996     scheme->reply()->setWebViewExperimental(webViewExperimental);
997     QQuickWebViewPrivate* d = webViewExperimental->d_func();
998     d->webPageProxy->registerApplicationScheme(scheme->scheme());
999 }
1000
1001 int QQuickWebViewExperimental::schemeDelegates_Count(QDeclarativeListProperty<QQuickUrlSchemeDelegate>* property)
1002 {
1003     return property->object->children().count();
1004 }
1005
1006 void QQuickWebViewExperimental::schemeDelegates_Clear(QDeclarativeListProperty<QQuickUrlSchemeDelegate>* property)
1007 {
1008     const QObjectList children = property->object->children();
1009     for (int index = 0; index < children.count(); index++) {
1010         QObject* child = children.at(index);
1011         child->setParent(0);
1012         delete child;
1013     }
1014 }
1015
1016 QDeclarativeListProperty<QQuickUrlSchemeDelegate> QQuickWebViewExperimental::schemeDelegates()
1017 {
1018     return QDeclarativeListProperty<QQuickUrlSchemeDelegate>(schemeParent, 0,
1019             QQuickWebViewExperimental::schemeDelegates_Append,
1020             QQuickWebViewExperimental::schemeDelegates_Count,
1021             QQuickWebViewExperimental::schemeDelegates_At,
1022             QQuickWebViewExperimental::schemeDelegates_Clear);
1023 }
1024
1025 void QQuickWebViewExperimental::invokeApplicationSchemeHandler(PassRefPtr<QtRefCountedNetworkRequestData> request)
1026 {
1027     RefPtr<QtRefCountedNetworkRequestData> req = request;
1028     const QObjectList children = schemeParent->children();
1029     for (int index = 0; index < children.count(); index++) {
1030         QQuickUrlSchemeDelegate* delegate = qobject_cast<QQuickUrlSchemeDelegate*>(children.at(index));
1031         if (!delegate)
1032             continue;
1033         if (!delegate->scheme().compare(QString(req->data().m_scheme), Qt::CaseInsensitive)) {
1034             delegate->request()->setNetworkRequestData(req);
1035             delegate->reply()->setNetworkRequestData(req);
1036             emit delegate->receivedRequest();
1037             return;
1038         }
1039     }
1040 }
1041
1042 void QQuickWebViewExperimental::sendApplicationSchemeReply(QQuickNetworkReply* reply)
1043 {
1044     d_ptr->webPageProxy->sendApplicationSchemeReply(reply);
1045 }
1046
1047 void QQuickWebViewExperimental::goForwardTo(int index)
1048 {
1049     d_ptr->navigationHistory->d->goForwardTo(index);
1050 }
1051
1052 void QQuickWebViewExperimental::goBackTo(int index)
1053 {
1054     d_ptr->navigationHistory->d->goBackTo(index);
1055 }
1056
1057 QWebViewportInfo* QQuickWebViewExperimental::viewportInfo()
1058 {
1059     return m_viewportInfo;
1060 }
1061
1062 QQuickWebPage* QQuickWebViewExperimental::page()
1063 {
1064     return q_ptr->page();
1065 }
1066
1067 QQuickWebView::QQuickWebView(QQuickItem* parent)
1068     : QQuickFlickable(parent)
1069     , d_ptr(createPrivateObject(this))
1070     , m_experimental(new QQuickWebViewExperimental(this))
1071 {
1072     Q_D(QQuickWebView);
1073     d->initialize();
1074 }
1075
1076 QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent)
1077     : QQuickFlickable(parent)
1078     , d_ptr(createPrivateObject(this))
1079     , m_experimental(new QQuickWebViewExperimental(this))
1080 {
1081     Q_D(QQuickWebView);
1082     d->initialize(contextRef, pageGroupRef);
1083 }
1084
1085 QQuickWebView::~QQuickWebView()
1086 {
1087 }
1088
1089 QQuickWebPage* QQuickWebView::page()
1090 {
1091     Q_D(QQuickWebView);
1092     return d->pageView.data();
1093 }
1094
1095 void QQuickWebView::goBack()
1096 {
1097     Q_D(QQuickWebView);
1098     d->webPageProxy->goBack();
1099 }
1100
1101 void QQuickWebView::goForward()
1102 {
1103     Q_D(QQuickWebView);
1104     d->webPageProxy->goForward();
1105 }
1106
1107 void QQuickWebView::stop()
1108 {
1109     Q_D(QQuickWebView);
1110     d->webPageProxy->stopLoading();
1111 }
1112
1113 void QQuickWebView::reload()
1114 {
1115     Q_D(QQuickWebView);
1116     const bool reloadFromOrigin = true;
1117     d->webPageProxy->reload(reloadFromOrigin);
1118 }
1119
1120 QUrl QQuickWebView::url() const
1121 {
1122     Q_D(const QQuickWebView);
1123     RefPtr<WebFrameProxy> mainFrame = d->webPageProxy->mainFrame();
1124     if (!mainFrame)
1125         return QUrl();
1126     return QUrl(QString(mainFrame->url()));
1127 }
1128
1129 void QQuickWebView::setUrl(const QUrl& url)
1130 {
1131     Q_D(QQuickWebView);
1132
1133     if (url.isEmpty())
1134         return;
1135
1136     if (!isComponentComplete()) {
1137         d->m_deferedUrlToLoad = url;
1138         return;
1139     }
1140
1141     d->webPageProxy->loadURL(url.toString());
1142 }
1143
1144 QUrl QQuickWebView::icon() const
1145 {
1146     Q_D(const QQuickWebView);
1147     return d->m_iconURL;
1148 }
1149
1150 int QQuickWebView::loadProgress() const
1151 {
1152     Q_D(const QQuickWebView);
1153     return d->pageLoadClient->loadProgress();
1154 }
1155
1156 bool QQuickWebView::canGoBack() const
1157 {
1158     Q_D(const QQuickWebView);
1159     return d->webPageProxy->canGoBack();
1160 }
1161
1162 bool QQuickWebView::canGoForward() const
1163 {
1164     Q_D(const QQuickWebView);
1165     return d->webPageProxy->canGoForward();
1166 }
1167
1168 bool QQuickWebView::loading() const
1169 {
1170     Q_D(const QQuickWebView);
1171     RefPtr<WebKit::WebFrameProxy> mainFrame = d->webPageProxy->mainFrame();
1172     return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
1173 }
1174
1175 QPointF QQuickWebView::mapToWebContent(const QPointF& pointInViewCoordinates) const
1176 {
1177     Q_D(const QQuickWebView);
1178     return d->pageView->transformFromItem().map(pointInViewCoordinates);
1179 }
1180
1181 QRectF QQuickWebView::mapRectToWebContent(const QRectF& rectInViewCoordinates) const
1182 {
1183     Q_D(const QQuickWebView);
1184     return d->pageView->transformFromItem().mapRect(rectInViewCoordinates);
1185 }
1186
1187 QPointF QQuickWebView::mapFromWebContent(const QPointF& pointInCSSCoordinates) const
1188 {
1189     Q_D(const QQuickWebView);
1190     return d->pageView->transformToItem().map(pointInCSSCoordinates);
1191 }
1192
1193 QRectF QQuickWebView::mapRectFromWebContent(const QRectF& rectInCSSCoordinates) const
1194 {
1195     Q_D(const QQuickWebView);
1196     return d->pageView->transformToItem().mapRect(rectInCSSCoordinates);
1197 }
1198
1199 QString QQuickWebView::title() const
1200 {
1201     Q_D(const QQuickWebView);
1202     return d->webPageProxy->pageTitle();
1203 }
1204
1205 QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const
1206 {
1207     Q_D(const QQuickWebView);
1208     const EditorState& state = d->webPageProxy->editorState();
1209
1210     switch(property) {
1211     case Qt::ImCursorRectangle:
1212         return QRectF(state.cursorRect);
1213     case Qt::ImFont:
1214         return QVariant();
1215     case Qt::ImCursorPosition:
1216         return QVariant(static_cast<int>(state.cursorPosition));
1217     case Qt::ImAnchorPosition:
1218         return QVariant(static_cast<int>(state.anchorPosition));
1219     case Qt::ImSurroundingText:
1220         return QString(state.surroundingText);
1221     case Qt::ImCurrentSelection:
1222         return QString(state.selectedText);
1223     case Qt::ImMaximumTextLength:
1224         return QVariant(); // No limit.
1225     case Qt::ImHints:
1226         return int(Qt::InputMethodHints(state.inputMethodHints));
1227     default:
1228         // Rely on the base implementation for ImEnabled, ImHints and ImPreferredLanguage.
1229         return QQuickFlickable::inputMethodQuery(property);
1230     }
1231 }
1232
1233 QQuickWebViewExperimental* QQuickWebView::experimental() const
1234 {
1235     return m_experimental;
1236 }
1237
1238 QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object)
1239 {
1240     return new QQuickWebViewAttached(object);
1241 }
1242
1243 void QQuickWebView::platformInitialize()
1244 {
1245     JSC::initializeThreading();
1246     WTF::initializeMainThread();
1247 }
1248
1249 void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
1250 {
1251     Q_D(QQuickWebView);
1252     QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
1253     if (newGeometry.size() != oldGeometry.size())
1254         d->updateViewportSize();
1255 }
1256
1257 void QQuickWebView::componentComplete()
1258 {
1259     Q_D(QQuickWebView);
1260     QQuickFlickable::componentComplete();
1261
1262     d->onComponentComplete();
1263     d->updateViewportSize();
1264 }
1265
1266 void QQuickWebView::keyPressEvent(QKeyEvent* event)
1267 {
1268     Q_D(QQuickWebView);
1269     d->pageView->eventHandler()->handleKeyPressEvent(event);
1270 }
1271
1272 void QQuickWebView::keyReleaseEvent(QKeyEvent* event)
1273 {
1274     Q_D(QQuickWebView);
1275     d->pageView->eventHandler()->handleKeyReleaseEvent(event);
1276 }
1277
1278 void QQuickWebView::inputMethodEvent(QInputMethodEvent* event)
1279 {
1280     Q_D(QQuickWebView);
1281     d->pageView->eventHandler()->handleInputMethodEvent(event);
1282 }
1283
1284 void QQuickWebView::focusInEvent(QFocusEvent* event)
1285 {
1286     Q_D(QQuickWebView);
1287     d->pageView->eventHandler()->handleFocusInEvent(event);
1288 }
1289
1290 void QQuickWebView::focusOutEvent(QFocusEvent* event)
1291 {
1292     Q_D(QQuickWebView);
1293     d->pageView->eventHandler()->handleFocusOutEvent(event);
1294 }
1295
1296 void QQuickWebView::touchEvent(QTouchEvent* event)
1297 {
1298     Q_D(QQuickWebView);
1299     if (d->m_dialogActive) {
1300         event->ignore();
1301         return;
1302     }
1303
1304     forceActiveFocus();
1305     d->pageView->eventHandler()->handleTouchEvent(event);
1306 }
1307
1308 void QQuickWebView::mousePressEvent(QMouseEvent* event)
1309 {
1310     Q_D(QQuickWebView);
1311     forceActiveFocus();
1312     d->pageView->eventHandler()->handleMousePressEvent(event);
1313 }
1314
1315 void QQuickWebView::mouseMoveEvent(QMouseEvent* event)
1316 {
1317     Q_D(QQuickWebView);
1318     d->pageView->eventHandler()->handleMouseMoveEvent(event);
1319 }
1320
1321 void QQuickWebView::mouseReleaseEvent(QMouseEvent* event)
1322 {
1323     Q_D(QQuickWebView);
1324     d->pageView->eventHandler()->handleMouseReleaseEvent(event);
1325 }
1326
1327 void QQuickWebView::mouseDoubleClickEvent(QMouseEvent* event)
1328 {
1329     Q_D(QQuickWebView);
1330     // If a MouseButtonDblClick was received then we got a MouseButtonPress before
1331     // handleMousePressEvent will take care of double clicks.
1332     d->pageView->eventHandler()->handleMousePressEvent(event);
1333 }
1334
1335 void QQuickWebView::wheelEvent(QWheelEvent* event)
1336 {
1337     Q_D(QQuickWebView);
1338     d->pageView->eventHandler()->handleWheelEvent(event);
1339 }
1340
1341 void QQuickWebView::hoverEnterEvent(QHoverEvent* event)
1342 {
1343     Q_D(QQuickWebView);
1344     // Map HoverEnter to Move, for WebKit the distinction doesn't matter.
1345     d->pageView->eventHandler()->handleHoverMoveEvent(event);
1346 }
1347
1348 void QQuickWebView::hoverMoveEvent(QHoverEvent* event)
1349 {
1350     Q_D(QQuickWebView);
1351     d->pageView->eventHandler()->handleHoverMoveEvent(event);
1352 }
1353
1354 void QQuickWebView::hoverLeaveEvent(QHoverEvent* event)
1355 {
1356     Q_D(QQuickWebView);
1357     d->pageView->eventHandler()->handleHoverLeaveEvent(event);
1358 }
1359
1360 void QQuickWebView::dragMoveEvent(QDragMoveEvent* event)
1361 {
1362     Q_D(QQuickWebView);
1363     d->pageView->eventHandler()->handleDragMoveEvent(event);
1364 }
1365
1366 void QQuickWebView::dragEnterEvent(QDragEnterEvent* event)
1367 {
1368     Q_D(QQuickWebView);
1369     d->pageView->eventHandler()->handleDragEnterEvent(event);
1370 }
1371
1372 void QQuickWebView::dragLeaveEvent(QDragLeaveEvent* event)
1373 {
1374     Q_D(QQuickWebView);
1375     d->pageView->eventHandler()->handleDragLeaveEvent(event);
1376 }
1377
1378 void QQuickWebView::dropEvent(QDropEvent* event)
1379 {
1380     Q_D(QQuickWebView);
1381     d->pageView->eventHandler()->handleDropEvent(event);
1382 }
1383
1384 bool QQuickWebView::event(QEvent* ev)
1385 {
1386     // Re-implemented for possible future use without breaking binary compatibility.
1387     return QQuickFlickable::event(ev);
1388 }
1389
1390 WKPageRef QQuickWebView::pageRef() const
1391 {
1392     Q_D(const QQuickWebView);
1393     return toAPI(d->webPageProxy.get());
1394 }
1395
1396 QPointF QQuickWebView::contentPos() const
1397 {
1398     Q_D(const QQuickWebView);
1399     return d->contentPos();
1400 }
1401
1402 void QQuickWebView::setContentPos(const QPointF& pos)
1403 {
1404     Q_D(QQuickWebView);
1405     d->setContentPos(pos);
1406 }
1407
1408 void QQuickWebView::handleFlickableMousePress(const QPointF& position, qint64 eventTimestampMillis)
1409 {
1410     QMouseEvent mouseEvent(QEvent::MouseButtonPress, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1411     mouseEvent.setTimestamp(eventTimestampMillis);
1412     QQuickFlickable::mousePressEvent(&mouseEvent);
1413 }
1414
1415 void QQuickWebView::handleFlickableMouseMove(const QPointF& position, qint64 eventTimestampMillis)
1416 {
1417     QMouseEvent mouseEvent(QEvent::MouseMove, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1418     mouseEvent.setTimestamp(eventTimestampMillis);
1419     QQuickFlickable::mouseMoveEvent(&mouseEvent);
1420 }
1421
1422 void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 eventTimestampMillis)
1423 {
1424     QMouseEvent mouseEvent(QEvent::MouseButtonRelease, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1425     mouseEvent.setTimestamp(eventTimestampMillis);
1426     QQuickFlickable::mouseReleaseEvent(&mouseEvent);
1427 }
1428
1429 /*!
1430     Loads the specified \a html as the content of the web view.
1431
1432     External objects such as stylesheets or images referenced in the HTML
1433     document are located relative to \a baseUrl.
1434
1435     \sa load()
1436 */
1437 void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl)
1438 {
1439     Q_D(QQuickWebView);
1440     d->webPageProxy->loadHTMLString(html, baseUrl.toString());
1441 }
1442
1443 QPointF QQuickWebView::pageItemPos()
1444 {
1445     Q_D(QQuickWebView);
1446     return d->pageItemPos();
1447 }
1448
1449 void QQuickWebView::updateContentsSize(const QSizeF& size)
1450 {
1451     Q_D(QQuickWebView);
1452     d->updateContentsSize(size);
1453 }
1454
1455 #include "moc_qquickwebview_p.cpp"