[Qt][WK2] History is not accessible in QML.
[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 "QtDialogRunner.h"
25 #include "QtWebPageProxy.h"
26 #include "UtilsQt.h"
27 #include "WebPageGroup.h"
28 #include "WebPreferences.h"
29
30 #include "qquickwebpage_p_p.h"
31 #include "qquickwebview_p_p.h"
32 #include "qwebnavigationhistory_p.h"
33 #include "qwebnavigationhistory_p_p.h"
34 #include "qwebpreferences_p_p.h"
35
36 #include <JavaScriptCore/InitializeThreading.h>
37 #include <QFileDialog>
38 #include <QInputDialog>
39 #include <QtQuick/QQuickCanvas>
40 #include <WKOpenPanelResultListener.h>
41
42 QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
43     : q_ptr(viewport)
44     , alertDialog(0)
45     , confirmDialog(0)
46     , promptDialog(0)
47     , itemSelector(0)
48     , postTransitionState(adoptPtr(new PostTransitionState(this)))
49     , isTransitioningToNewPage(false)
50     , pageIsSuspended(false)
51 {
52     viewport->setFlags(QQuickItem::ItemClipsChildrenToShape);
53
54     QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged()));
55     pageView.reset(new QQuickWebPage(viewport));
56
57     pageClient.reset(new QtPageClient());
58
59     QQuickWebPagePrivate* const pageViewPrivate = pageView.data()->d;
60     setPageProxy(new QtWebPageProxy(pageView.data(), q_ptr, pageClient.data(), contextRef, pageGroupRef));
61     pageViewPrivate->setPageProxy(pageProxy.data());
62
63     pageLoadClient.reset(new QtWebPageLoadClient(pageProxy->pageRef(), q_ptr));
64     pagePolicyClient.reset(new QtWebPagePolicyClient(pageProxy->pageRef(), q_ptr));
65     pageUIClient.reset(new QtWebPageUIClient(pageProxy->pageRef(), q_ptr));
66     eventHandler.reset(new QtWebPageEventHandler(pageProxy->pageRef(), q_ptr));
67
68     // Any page setting should preferrable be set before creating the page, so set them here:
69     setUseTraditionalDesktopBehaviour(false);
70     QWebPreferencesPrivate::get(pageProxy->preferences())->setAttribute(QWebPreferencesPrivate::AcceleratedCompositingEnabled, true);
71
72     pageClient->setEventHandler(eventHandler.data());
73     pageClient->setPageProxy(pageProxy.data());
74
75     // Creates a page with the page creation parameters.
76     pageProxy->init(eventHandler.data());
77
78     // Trigger setting of correct visibility flags after everything was allocated and initialized.
79     _q_onVisibleChanged();
80 }
81
82 QQuickWebViewPrivate::~QQuickWebViewPrivate()
83 {
84     if (interactionEngine)
85         interactionEngine->disconnect();
86 }
87
88 void QQuickWebViewPrivate::enableMouseEvents()
89 {
90     Q_Q(QQuickWebView);
91     q->setAcceptedMouseButtons(Qt::MouseButtonMask);
92     q->setAcceptHoverEvents(true);
93     pageView->setAcceptedMouseButtons(Qt::MouseButtonMask);
94     pageView->setAcceptHoverEvents(true);
95 }
96
97 void QQuickWebViewPrivate::disableMouseEvents()
98 {
99     Q_Q(QQuickWebView);
100     q->setAcceptedMouseButtons(Qt::NoButton);
101     q->setAcceptHoverEvents(false);
102     pageView->setAcceptedMouseButtons(Qt::NoButton);
103     pageView->setAcceptHoverEvents(false);
104 }
105
106 void QQuickWebViewPrivate::initializeDesktop(QQuickWebView* viewport)
107 {
108     if (interactionEngine) {
109         QObject::disconnect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend()));
110         QObject::disconnect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume()));
111         QObject::disconnect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&)));
112     }
113     interactionEngine.reset(0);
114     eventHandler->setViewportInteractionEngine(0);
115     enableMouseEvents();
116 }
117
118 void QQuickWebViewPrivate::initializeTouch(QQuickWebView* viewport)
119 {
120     interactionEngine.reset(new QtViewportInteractionEngine(viewport, pageView.data()));
121     eventHandler->setViewportInteractionEngine(interactionEngine.data());
122     disableMouseEvents();
123     QObject::connect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend()));
124     QObject::connect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume()));
125     QObject::connect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&)));
126     updateViewportSize();
127 }
128
129 void QQuickWebViewPrivate::loadDidCommit()
130 {
131     // Due to entering provisional load before committing, we
132     // might actually be suspended here.
133
134     if (useTraditionalDesktopBehaviour)
135         return;
136
137     isTransitioningToNewPage = true;
138 }
139
140 void QQuickWebViewPrivate::didFinishFirstNonEmptyLayout()
141 {
142     if (useTraditionalDesktopBehaviour)
143         return;
144
145     if (!pageIsSuspended) {
146         isTransitioningToNewPage = false;
147         postTransitionState->apply();
148     }
149 }
150
151 void QQuickWebViewPrivate::_q_suspend()
152 {
153     pageIsSuspended = true;
154 }
155
156 void QQuickWebViewPrivate::_q_resume()
157 {
158     pageIsSuspended = false;
159
160     if (isTransitioningToNewPage) {
161         isTransitioningToNewPage = false;
162         postTransitionState->apply();
163     }
164
165     updateVisibleContentRect();
166 }
167
168 void QQuickWebViewPrivate::didChangeContentsSize(const QSize& newSize)
169 {
170     if (useTraditionalDesktopBehaviour)
171         return;
172
173     // FIXME: We probably want to handle suspend here as well
174     if (isTransitioningToNewPage) {
175         postTransitionState->contentsSize = newSize;
176         return;
177     }
178
179     pageView->setWidth(newSize.width());
180     pageView->setHeight(newSize.height());
181 }
182
183 void QQuickWebViewPrivate::didChangeViewportProperties(const WebCore::ViewportArguments& args)
184 {
185     if (useTraditionalDesktopBehaviour)
186         return;
187
188     viewportArguments = args;
189
190     if (isTransitioningToNewPage)
191         return;
192
193     interactionEngine->applyConstraints(computeViewportConstraints());
194 }
195
196 void QQuickWebViewPrivate::didChangeBackForwardList()
197 {
198     pageProxy->navigationHistory()->d->reset();
199 }
200
201 void QQuickWebViewPrivate::scrollPositionRequested(const QPoint& pos)
202 {
203     if (!useTraditionalDesktopBehaviour)
204         interactionEngine->pagePositionRequest(pos);
205 }
206
207 void QQuickWebViewPrivate::updateVisibleContentRect()
208 {
209     Q_Q(QQuickWebView);
210     const QRectF visibleRectInPageViewCoordinates = q->mapRectToItem(pageView.data(), q->boundingRect()).intersected(pageView->boundingRect());
211     float scale = pageView->scale();
212     pageProxy->setVisibleContentRectAndScale(visibleRectInPageViewCoordinates, scale);
213 }
214
215 void QQuickWebViewPrivate::_q_viewportTrajectoryVectorChanged(const QPointF& trajectoryVector)
216 {
217     pageProxy->setVisibleContentRectTrajectoryVector(trajectoryVector);
218 }
219
220 void QQuickWebViewPrivate::_q_onVisibleChanged()
221 {
222     WebPageProxy* wkPage = toImpl(pageProxy->pageRef());
223
224     wkPage->viewStateDidChange(WebPageProxy::ViewIsVisible);
225 }
226
227 void QQuickWebViewPrivate::updateViewportSize()
228 {
229     Q_Q(QQuickWebView);
230     QSize viewportSize = q->boundingRect().size().toSize();
231
232     if (viewportSize.isEmpty())
233         return;
234
235     WebPageProxy* wkPage = toImpl(pageProxy->pageRef());
236     // Let the WebProcess know about the new viewport size, so that
237     // it can resize the content accordingly.
238     wkPage->setViewportSize(viewportSize);
239
240     interactionEngine->applyConstraints(computeViewportConstraints());
241     updateVisibleContentRect();
242 }
243
244 QtViewportInteractionEngine::Constraints QQuickWebViewPrivate::computeViewportConstraints()
245 {
246     Q_Q(QQuickWebView);
247
248     QtViewportInteractionEngine::Constraints newConstraints;
249     QSize availableSize = q->boundingRect().size().toSize();
250
251     // Return default values for zero sized viewport.
252     if (availableSize.isEmpty())
253         return newConstraints;
254
255     WebPageProxy* wkPage = toImpl(pageProxy->pageRef());
256     WebPreferences* wkPrefs = wkPage->pageGroup()->preferences();
257
258     // FIXME: Remove later; Hardcode some values for now to make sure the DPI adjustment is being tested.
259     wkPrefs->setDeviceDPI(240);
260     wkPrefs->setDeviceWidth(480);
261     wkPrefs->setDeviceHeight(720);
262
263     int minimumLayoutFallbackWidth = qMax<int>(wkPrefs->layoutFallbackWidth(), availableSize.width());
264
265     WebCore::ViewportAttributes attr = WebCore::computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, wkPrefs->deviceWidth(), wkPrefs->deviceHeight(), wkPrefs->deviceDPI(), availableSize);
266     WebCore::restrictMinimumScaleFactorToViewportSize(attr, availableSize);
267     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attr);
268
269     newConstraints.initialScale = attr.initialScale;
270     newConstraints.minimumScale = attr.minimumScale;
271     newConstraints.maximumScale = attr.maximumScale;
272     newConstraints.devicePixelRatio = attr.devicePixelRatio;
273     newConstraints.isUserScalable = !!attr.userScalable;
274
275     return newConstraints;
276 }
277
278 void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText)
279 {
280     if (!alertDialog)
281         return;
282
283     Q_Q(QQuickWebView);
284     QtDialogRunner dialogRunner;
285     if (!dialogRunner.initForAlert(alertDialog, q, alertText))
286         return;
287     setViewInAttachedProperties(dialogRunner.dialog());
288
289     disableMouseEvents();
290     dialogRunner.exec();
291     enableMouseEvents();
292 }
293
294 bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message)
295 {
296     if (!confirmDialog)
297         return true;
298
299     Q_Q(QQuickWebView);
300     QtDialogRunner dialogRunner;
301     if (!dialogRunner.initForConfirm(confirmDialog, q, message))
302         return true;
303     setViewInAttachedProperties(dialogRunner.dialog());
304
305     disableMouseEvents();
306     dialogRunner.exec();
307     enableMouseEvents();
308
309     return dialogRunner.wasAccepted();
310 }
311
312 QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok)
313 {
314     if (!promptDialog) {
315         ok = true;
316         return defaultValue;
317     }
318
319     Q_Q(QQuickWebView);
320     QtDialogRunner dialogRunner;
321     if (!dialogRunner.initForPrompt(promptDialog, q, message, defaultValue)) {
322         ok = true;
323         return defaultValue;
324     }
325     setViewInAttachedProperties(dialogRunner.dialog());
326
327     disableMouseEvents();
328     dialogRunner.exec();
329     enableMouseEvents();
330
331     ok = dialogRunner.wasAccepted();
332     return dialogRunner.result();
333 }
334
335 void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type)
336 {
337 #ifndef QT_NO_FILEDIALOG
338     Q_Q(QQuickWebView);
339     openPanelResultListener = listenerRef;
340
341     // Qt does not support multiple files suggestion, so we get just the first suggestion.
342     QString selectedFileName;
343     if (!selectedFileNames.isEmpty())
344         selectedFileName = selectedFileNames.at(0);
345
346     Q_ASSERT(!fileDialog);
347
348     QWindow* window = q->canvas();
349     if (!window)
350         return;
351
352     fileDialog = new QFileDialog(0, QString(), selectedFileName);
353     fileDialog->window()->winId(); // Ensure that the dialog has a window
354     Q_ASSERT(fileDialog->window()->windowHandle());
355     fileDialog->window()->windowHandle()->setTransientParent(window);
356
357     fileDialog->open(q, SLOT(_q_onOpenPanelFilesSelected()));
358
359     q->connect(fileDialog, SIGNAL(finished(int)), SLOT(_q_onOpenPanelFinished(int)));
360 #endif
361 }
362
363 void QQuickWebViewPrivate::_q_onOpenPanelFilesSelected()
364 {
365     const QStringList fileList = fileDialog->selectedFiles();
366     Vector<RefPtr<APIObject> > wkFiles(fileList.size());
367
368     for (unsigned i = 0; i < fileList.size(); ++i)
369         wkFiles[i] = WebURL::create(QUrl::fromLocalFile(fileList.at(i)).toString());
370
371     WKOpenPanelResultListenerChooseFiles(openPanelResultListener, toAPI(ImmutableArray::adopt(wkFiles).leakRef()));
372 }
373
374 void QQuickWebViewPrivate::_q_onOpenPanelFinished(int result)
375 {
376     if (result == QDialog::Rejected)
377         WKOpenPanelResultListenerCancel(openPanelResultListener);
378
379     fileDialog->deleteLater();
380     fileDialog = 0;
381 }
382
383 void QQuickWebViewPrivate::setUseTraditionalDesktopBehaviour(bool enable)
384 {
385     Q_Q(QQuickWebView);
386
387     // Do not guard, testing for the same value, as we call this from the constructor.
388
389     toImpl(pageProxy->pageRef())->setUseFixedLayout(!enable);
390
391     useTraditionalDesktopBehaviour = enable;
392     if (useTraditionalDesktopBehaviour)
393         initializeDesktop(q);
394     else
395         initializeTouch(q);
396 }
397
398 void QQuickWebViewPrivate::setViewInAttachedProperties(QObject* object)
399 {
400     Q_Q(QQuickWebView);
401     QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object));
402     attached->setView(q);
403 }
404
405 /*!
406     \qmlsignal WebView::onNavigationRequested(request)
407
408     This signal is emitted for every navigation request. The request object contains url, button and modifiers properties
409     describing the navigation action, e.g. "a middle click with shift key pressed to 'http://qt-project.org'".
410
411     The navigation will be accepted by default. To change that, one can set the action property to WebView.IgnoreRequest to reject
412     the request or WebView.DownloadRequest to trigger a download instead of navigating to the url.
413
414     The request object cannot be used after the signal handler function ends.
415 */
416
417 void QQuickWebViewPrivate::setPageProxy(QtWebPageProxy* pageProxy)
418 {
419     Q_Q(QQuickWebView);
420     this->pageProxy.reset(pageProxy);
421     QObject::connect(pageProxy, SIGNAL(receivedMessageFromNavigatorQtObject(QVariantMap)), q, SIGNAL(messageReceived(QVariantMap)));
422 }
423
424 QQuickWebViewAttached::QQuickWebViewAttached(QObject* object)
425     : QObject(object)
426     , m_view(0)
427 {
428
429 }
430
431 void QQuickWebViewAttached::setView(QQuickWebView* view)
432 {
433     if (m_view == view)
434         return;
435     m_view = view;
436     emit viewChanged();
437 }
438
439 QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView)
440     : QObject(webView)
441     , q_ptr(webView)
442     , d_ptr(webView->d_ptr.data())
443 {
444 }
445
446 QQuickWebViewExperimental::~QQuickWebViewExperimental()
447 {
448 }
449
450 void QQuickWebViewExperimental::setUseTraditionalDesktopBehaviour(bool enable)
451 {
452     Q_D(QQuickWebView);
453
454     if (enable == d->useTraditionalDesktopBehaviour)
455         return;
456
457     d->setUseTraditionalDesktopBehaviour(enable);
458 }
459
460 QDeclarativeComponent* QQuickWebViewExperimental::alertDialog() const
461 {
462     Q_D(const QQuickWebView);
463     return d->alertDialog;
464 }
465
466 void QQuickWebViewExperimental::setAlertDialog(QDeclarativeComponent* alertDialog)
467 {
468     Q_D(QQuickWebView);
469     if (d->alertDialog == alertDialog)
470         return;
471     d->alertDialog = alertDialog;
472     emit alertDialogChanged();
473 }
474
475 QDeclarativeComponent* QQuickWebViewExperimental::confirmDialog() const
476 {
477     Q_D(const QQuickWebView);
478     return d->confirmDialog;
479 }
480
481 void QQuickWebViewExperimental::setConfirmDialog(QDeclarativeComponent* confirmDialog)
482 {
483     Q_D(QQuickWebView);
484     if (d->confirmDialog == confirmDialog)
485         return;
486     d->confirmDialog = confirmDialog;
487     emit confirmDialogChanged();
488 }
489
490 QWebNavigationHistory* QQuickWebViewExperimental::navigationHistory() const
491 {
492     return d_ptr->pageProxy->navigationHistory();
493 }
494
495 QDeclarativeComponent* QQuickWebViewExperimental::promptDialog() const
496 {
497     Q_D(const QQuickWebView);
498     return d->promptDialog;
499 }
500
501 void QQuickWebViewExperimental::setPromptDialog(QDeclarativeComponent* promptDialog)
502 {
503     Q_D(QQuickWebView);
504     if (d->promptDialog == promptDialog)
505         return;
506     d->promptDialog = promptDialog;
507     emit promptDialogChanged();
508 }
509
510 QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const
511 {
512     Q_D(const QQuickWebView);
513     return d->itemSelector;
514 }
515
516 void QQuickWebViewExperimental::setItemSelector(QDeclarativeComponent* itemSelector)
517 {
518     Q_D(QQuickWebView);
519     if (d->itemSelector == itemSelector)
520         return;
521     d->itemSelector = itemSelector;
522     emit itemSelectorChanged();
523 }
524
525 bool QQuickWebViewExperimental::useTraditionalDesktopBehaviour() const
526 {
527     Q_D(const QQuickWebView);
528     return d->useTraditionalDesktopBehaviour;
529 }
530
531 void QQuickWebViewExperimental::goForwardTo(int index)
532 {
533     d_ptr->pageProxy->goForwardTo(index);
534 }
535
536 void QQuickWebViewExperimental::goBackTo(int index)
537 {
538     d_ptr->pageProxy->goBackTo(index);
539 }
540
541 QQuickWebView::QQuickWebView(QQuickItem* parent)
542     : QQuickItem(parent)
543     , d_ptr(new QQuickWebViewPrivate(this))
544     , m_experimental(new QQuickWebViewExperimental(this))
545 {
546     Q_D(QQuickWebView);
547     d->initializeTouch(this);
548 }
549
550 QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent)
551     : QQuickItem(parent)
552     , d_ptr(new QQuickWebViewPrivate(this, contextRef, pageGroupRef))
553     , m_experimental(new QQuickWebViewExperimental(this))
554 {
555 }
556
557 QQuickWebView::~QQuickWebView()
558 {
559 }
560
561 QQuickWebPage* QQuickWebView::page()
562 {
563     Q_D(QQuickWebView);
564     return d->pageView.data();
565 }
566
567 void QQuickWebView::load(const QUrl& url)
568 {
569     Q_D(QQuickWebView);
570     d->pageProxy->load(url);
571 }
572
573 void QQuickWebView::postMessage(const QString& message)
574 {
575     Q_D(QQuickWebView);
576     d->pageProxy->postMessageToNavigatorQtObject(message);
577 }
578
579 void QQuickWebView::goBack()
580 {
581     Q_D(QQuickWebView);
582     d->pageProxy->goBack();
583 }
584
585 void QQuickWebView::goForward()
586 {
587     Q_D(QQuickWebView);
588     d->pageProxy->goForward();
589 }
590
591 void QQuickWebView::stop()
592 {
593     Q_D(QQuickWebView);
594     d->pageProxy->stop();
595 }
596
597 void QQuickWebView::reload()
598 {
599     Q_D(QQuickWebView);
600     d->pageProxy->reload();
601 }
602
603 QUrl QQuickWebView::url() const
604 {
605     Q_D(const QQuickWebView);
606     return d->pageProxy->url();
607 }
608
609 int QQuickWebView::loadProgress() const
610 {
611     Q_D(const QQuickWebView);
612     return d->pageLoadClient->loadProgress();
613 }
614
615 bool QQuickWebView::canGoBack() const
616 {
617     Q_D(const QQuickWebView);
618     return d->pageProxy->canGoBack();
619 }
620
621 bool QQuickWebView::canGoForward() const
622 {
623     Q_D(const QQuickWebView);
624     return d->pageProxy->canGoForward();
625 }
626
627 bool QQuickWebView::loading() const
628 {
629     Q_D(const QQuickWebView);
630     return d->pageProxy->loading();
631 }
632
633 bool QQuickWebView::canReload() const
634 {
635     Q_D(const QQuickWebView);
636     return d->pageProxy->canReload();
637 }
638
639 QString QQuickWebView::title() const
640 {
641     Q_D(const QQuickWebView);
642     return d->pageProxy->title();
643 }
644
645 QWebPreferences* QQuickWebView::preferences() const
646 {
647     Q_D(const QQuickWebView);
648     return d->pageProxy->preferences();
649 }
650
651 QQuickWebViewExperimental* QQuickWebView::experimental() const
652 {
653     return m_experimental;
654 }
655
656 QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object)
657 {
658     return new QQuickWebViewAttached(object);
659 }
660
661 void QQuickWebView::platformInitialize()
662 {
663     JSC::initializeThreading();
664     WTF::initializeMainThread();
665 }
666
667 void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
668 {
669     Q_D(QQuickWebView);
670     QQuickItem::geometryChanged(newGeometry, oldGeometry);
671     if (newGeometry.size() != oldGeometry.size()) {
672         if (d->useTraditionalDesktopBehaviour) {
673             d->pageView->setWidth(newGeometry.width());
674             d->pageView->setHeight(newGeometry.height());
675         } else
676             d->updateViewportSize();
677     }
678 }
679
680 void QQuickWebView::focusInEvent(QFocusEvent* event)
681 {
682     Q_D(QQuickWebView);
683     d->pageView->event(event);
684 }
685
686 void QQuickWebView::focusOutEvent(QFocusEvent* event)
687 {
688     Q_D(QQuickWebView);
689     d->pageView->event(event);
690 }
691
692 void QQuickWebView::touchEvent(QTouchEvent* event)
693 {
694     forceActiveFocus();
695     QQuickItem::touchEvent(event);
696 }
697
698 WKPageRef QQuickWebView::pageRef() const
699 {
700     Q_D(const QQuickWebView);
701     return d->pageProxy->pageRef();
702 }
703
704 /*!
705     Loads the specified \a html as the content of the web view.
706
707     External objects such as stylesheets or images referenced in the HTML
708     document are located relative to \a baseUrl.
709
710     \sa load()
711 */
712 void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl)
713 {
714     Q_D(QQuickWebView);
715     d->pageProxy->loadHTMLString(html, baseUrl);
716 }
717
718 #include "moc_qquickwebview_p.cpp"