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