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