[Qt] The WebView should be flickable only using touch events
[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 "PageViewportControllerClientQt.h"
27 #include "QtDialogRunner.h"
28 #include "QtDownloadManager.h"
29 #include "QtWebContext.h"
30 #include "QtWebError.h"
31 #include "QtWebIconDatabaseClient.h"
32 #include "QtWebPageEventHandler.h"
33 #include "QtWebPageLoadClient.h"
34 #include "QtWebPagePolicyClient.h"
35 #include "WebBackForwardList.h"
36 #if ENABLE(INSPECTOR_SERVER)
37 #include "WebInspectorProxy.h"
38 #include "WebInspectorServer.h"
39 #endif
40 #if ENABLE(FULLSCREEN_API)
41 #include "WebFullScreenManagerProxy.h"
42 #endif
43 #include "WebPageGroup.h"
44 #include "WebPreferences.h"
45 #include "qquicknetworkreply_p.h"
46 #include "qquicknetworkrequest_p.h"
47 #include "qquickwebpage_p_p.h"
48 #include "qquickwebview_p_p.h"
49 #include "qwebdownloaditem_p_p.h"
50 #include "qwebiconimageprovider_p.h"
51 #include "qwebkittest_p.h"
52 #include "qwebloadrequest_p.h"
53 #include "qwebnavigationhistory_p.h"
54 #include "qwebnavigationhistory_p_p.h"
55 #include "qwebpreferences_p.h"
56 #include "qwebpreferences_p_p.h"
57 #include <JavaScriptCore/InitializeThreading.h>
58 #include <JavaScriptCore/JSBase.h>
59 #include <JavaScriptCore/JSRetainPtr.h>
60 #include <QDateTime>
61 #include <QtCore/QFile>
62 #include <QtQml/QJSValue>
63 #include <QtQuick/QQuickView>
64 #include <WKOpenPanelResultListener.h>
65 #include <WKSerializedScriptValue.h>
66 #include <WebCore/IntPoint.h>
67 #include <WebCore/IntRect.h>
68 #include <wtf/Assertions.h>
69 #include <wtf/MainThread.h>
70 #include <wtf/Vector.h>
71 #include <wtf/text/WTFString.h>
72
73 using namespace WebCore;
74 using namespace WebKit;
75
76 static bool s_flickableViewportEnabled = true;
77 static const int kAxisLockSampleCount = 5;
78 static const qreal kAxisLockVelocityThreshold = 300;
79 static const qreal kAxisLockVelocityDirectionThreshold = 50;
80
81 struct JSCallbackClosure {
82     QPointer<QObject> receiver;
83     QByteArray method;
84     QJSValue value;
85 };
86
87 static inline QString toQString(JSStringRef string)
88 {
89     return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(string)), JSStringGetLength(string));
90 }
91
92 static inline QJSValue toQJSValue(JSStringRef string)
93 {
94     return QJSValue(toQString(string));
95 }
96
97 static QJSValue buildQJSValue(QJSEngine* engine, JSGlobalContextRef context, JSValueRef value, int depth)
98 {
99     QJSValue var;
100     JSValueRef exception = 0;
101
102     if (depth > 10)
103         return var;
104
105     switch (JSValueGetType(context, value)) {
106     case kJSTypeBoolean:
107         var = QJSValue(JSValueToBoolean(context, value));
108         break;
109     case kJSTypeNumber:
110         {
111             double number = JSValueToNumber(context, value, &exception);
112             if (!exception)
113                 var = QJSValue(number);
114         }
115         break;
116     case kJSTypeString:
117         {
118             JSRetainPtr<JSStringRef> string = JSValueToStringCopy(context, value, &exception);
119             if (!exception)
120                 var = toQJSValue(string.get());
121         }
122         break;
123     case kJSTypeObject:
124         {
125             JSObjectRef obj = JSValueToObject(context, value, &exception);
126
127             JSPropertyNameArrayRef names = JSObjectCopyPropertyNames(context, obj);
128             size_t length = JSPropertyNameArrayGetCount(names);
129
130             var = engine->newObject();
131
132             for (size_t i = 0; i < length; ++i) {
133                 JSRetainPtr<JSStringRef> name = JSPropertyNameArrayGetNameAtIndex(names, i);
134                 JSValueRef property = JSObjectGetProperty(context, obj, name.get(), &exception);
135
136                 if (!exception) {
137                     QJSValue value = buildQJSValue(engine, context, property, depth + 1);
138                     var.setProperty(toQString(name.get()), value);
139                 }
140             }
141         }
142         break;
143     }
144     return var;
145 }
146
147 static void javaScriptCallback(WKSerializedScriptValueRef valueRef, WKErrorRef, void* data)
148 {
149     JSCallbackClosure* closure = reinterpret_cast<JSCallbackClosure*>(data);
150
151     if (closure->method.size())
152         QMetaObject::invokeMethod(closure->receiver, closure->method);
153     else {
154         QJSValue function = closure->value;
155
156         // If a callable function is supplied, we build a JavaScript value accessible
157         // in the QML engine, and calls the function with that.
158         if (function.isCallable()) {
159             QJSValue var;
160             if (valueRef) {
161                 // FIXME: Slow but OK for now.
162                 JSGlobalContextRef context = JSGlobalContextCreate(0);
163
164                 JSValueRef exception = 0;
165                 JSValueRef value = WKSerializedScriptValueDeserialize(valueRef, context, &exception);
166                 var = buildQJSValue(function.engine(), context, value, /* depth */ 0);
167
168                 JSGlobalContextRelease(context);
169             }
170
171             QList<QJSValue> args;
172             args.append(var);
173             function.call(args);
174         }
175     }
176
177     delete closure;
178 }
179
180 static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject)
181 {
182     if (s_flickableViewportEnabled)
183         return new QQuickWebViewFlickablePrivate(publicObject);
184     return new QQuickWebViewLegacyPrivate(publicObject);
185 }
186
187 QQuickWebViewPrivate::FlickableAxisLocker::FlickableAxisLocker()
188     : m_allowedDirection(QQuickFlickable::AutoFlickDirection)
189     , m_time(0), m_sampleCount(0)
190 {
191 }
192
193 QVector2D QQuickWebViewPrivate::FlickableAxisLocker::touchVelocity(const QTouchEvent* event)
194 {
195     static bool touchVelocityAvailable = event->device()->capabilities().testFlag(QTouchDevice::Velocity);
196     const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
197
198     if (touchVelocityAvailable)
199         return touchPoint.velocity();
200
201     const QLineF movementLine(touchPoint.pos(), m_initialPosition);
202     const ulong elapsed = event->timestamp() - m_time;
203
204     if (!elapsed)
205         return QVector2D(0, 0);
206
207     // Calculate an approximate velocity vector in the unit of pixel / second.
208     return QVector2D(1000 * movementLine.dx() / elapsed, 1000 * movementLine.dy() / elapsed);
209 }
210
211 void QQuickWebViewPrivate::FlickableAxisLocker::update(const QTouchEvent* event)
212 {
213     ASSERT(event->touchPoints().size() == 1);
214     const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
215
216     ++m_sampleCount;
217
218     if (m_sampleCount == 1) {
219         m_initialPosition = touchPoint.pos();
220         m_time = event->timestamp();
221         return;
222     }
223
224     if (m_sampleCount > kAxisLockSampleCount
225             || m_allowedDirection == QQuickFlickable::HorizontalFlick
226             || m_allowedDirection == QQuickFlickable::VerticalFlick)
227         return;
228
229     QVector2D velocity = touchVelocity(event);
230
231     qreal directionIndicator = qAbs(velocity.x()) - qAbs(velocity.y());
232
233     if (velocity.length() > kAxisLockVelocityThreshold && qAbs(directionIndicator) > kAxisLockVelocityDirectionThreshold)
234         m_allowedDirection = (directionIndicator > 0) ? QQuickFlickable::HorizontalFlick : QQuickFlickable::VerticalFlick;
235 }
236
237 void QQuickWebViewPrivate::FlickableAxisLocker::setReferencePosition(const QPointF& position)
238 {
239     m_lockReferencePosition = position;
240 }
241
242 void QQuickWebViewPrivate::FlickableAxisLocker::reset()
243 {
244     m_allowedDirection = QQuickFlickable::AutoFlickDirection;
245     m_sampleCount = 0;
246 }
247
248 QPointF QQuickWebViewPrivate::FlickableAxisLocker::adjust(const QPointF& position)
249 {
250     if (m_allowedDirection == QQuickFlickable::HorizontalFlick)
251         return QPointF(position.x(), m_lockReferencePosition.y());
252
253     if (m_allowedDirection == QQuickFlickable::VerticalFlick)
254         return QPointF(m_lockReferencePosition.x(), position.y());
255
256     return position;
257 }
258
259 QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
260     : q_ptr(viewport)
261     , experimental(new QQuickWebViewExperimental(viewport, this))
262     , alertDialog(0)
263     , confirmDialog(0)
264     , promptDialog(0)
265     , authenticationDialog(0)
266     , certificateVerificationDialog(0)
267     , itemSelector(0)
268     , proxyAuthenticationDialog(0)
269     , filePicker(0)
270     , databaseQuotaDialog(0)
271     , colorChooser(0)
272     , m_betweenLoadCommitAndFirstFrame(false)
273     , m_useDefaultContentItemSize(true)
274     , m_navigatorQtObjectEnabled(false)
275     , m_renderToOffscreenBuffer(false)
276     , m_allowAnyHTTPSCertificateForLocalHost(false)
277     , m_loadProgress(0)
278 {
279     viewport->setClip(true);
280     viewport->setPixelAligned(true);
281     QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged()));
282     QObject::connect(viewport, SIGNAL(urlChanged()), viewport, SLOT(_q_onUrlChanged()));
283     pageView.reset(new QQuickWebPage(viewport));
284 }
285
286 QQuickWebViewPrivate::~QQuickWebViewPrivate()
287 {
288     webPageProxy->close();
289 }
290
291 // Note: we delay this initialization to make sure that QQuickWebView has its d-ptr in-place.
292 void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
293 {
294     RefPtr<WebPageGroup> pageGroup;
295     if (pageGroupRef)
296         pageGroup = toImpl(pageGroupRef);
297     else
298         pageGroup = WebPageGroup::create();
299
300     context = contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext();
301     webPageProxy = context->createWebPage(&pageClient, pageGroup.get());
302     webPageProxy->setUseFixedLayout(s_flickableViewportEnabled);
303 #if ENABLE(FULLSCREEN_API)
304     webPageProxy->fullScreenManager()->setWebView(q_ptr);
305 #endif
306
307     QQuickWebPagePrivate* const pageViewPrivate = pageView.data()->d;
308     pageViewPrivate->initialize(webPageProxy.get());
309
310     pageLoadClient.reset(new QtWebPageLoadClient(toAPI(webPageProxy.get()), q_ptr));
311     pagePolicyClient.reset(new QtWebPagePolicyClient(toAPI(webPageProxy.get()), q_ptr));
312     pageUIClient.reset(new QtWebPageUIClient(toAPI(webPageProxy.get()), q_ptr));
313     navigationHistory = adoptPtr(QWebNavigationHistoryPrivate::createHistory(toAPI(webPageProxy.get())));
314
315     QtWebIconDatabaseClient* iconDatabase = context->iconDatabase();
316     QObject::connect(iconDatabase, SIGNAL(iconChangedForPageURL(QString)), q_ptr, SLOT(_q_onIconChangedForPageURL(QString)));
317
318     // Any page setting should preferrable be set before creating the page.
319     webPageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true);
320     webPageProxy->pageGroup()->preferences()->setForceCompositingMode(true);
321     webPageProxy->pageGroup()->preferences()->setFrameFlatteningEnabled(true);
322
323     pageClient.initialize(q_ptr, pageViewPrivate->eventHandler.data(), &undoController);
324     webPageProxy->initializeWebPage();
325
326     q_ptr->setAcceptedMouseButtons(Qt::MouseButtonMask);
327     q_ptr->setAcceptHoverEvents(true);
328     q_ptr->setFlags(QQuickItem::ItemAcceptsDrops);
329 }
330
331 void QQuickWebViewPrivate::loadDidStop()
332 {
333     Q_Q(QQuickWebView);
334     ASSERT(!q->loading());
335     QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadStoppedStatus);
336     emit q->loadingChanged(&loadRequest);
337 }
338
339 void QQuickWebViewPrivate::setTransparentBackground(bool enable)
340 {
341     webPageProxy->setDrawsTransparentBackground(enable);
342 }
343
344 bool QQuickWebViewPrivate::transparentBackground() const
345 {
346     return webPageProxy->drawsTransparentBackground();
347 }
348
349 void QQuickWebViewPrivate::provisionalLoadDidStart(const WTF::String& url)
350 {
351     Q_Q(QQuickWebView);
352
353     q->emitUrlChangeIfNeeded();
354
355     QWebLoadRequest loadRequest(QString(url), QQuickWebView::LoadStartedStatus);
356     emit q->loadingChanged(&loadRequest);
357 }
358
359 void QQuickWebViewPrivate::didReceiveServerRedirectForProvisionalLoad(const WTF::String&)
360 {
361     Q_Q(QQuickWebView);
362
363     q->emitUrlChangeIfNeeded();
364 }
365
366 void QQuickWebViewPrivate::loadDidCommit()
367 {
368     Q_Q(QQuickWebView);
369     ASSERT(q->loading());
370
371     m_betweenLoadCommitAndFirstFrame = true;
372     emit q->navigationHistoryChanged();
373     emit q->titleChanged();
374 }
375
376 void QQuickWebViewPrivate::didSameDocumentNavigation()
377 {
378     Q_Q(QQuickWebView);
379
380     q->emitUrlChangeIfNeeded();
381     emit q->navigationHistoryChanged();
382 }
383
384 void QQuickWebViewPrivate::titleDidChange()
385 {
386     Q_Q(QQuickWebView);
387
388     emit q->titleChanged();
389 }
390
391 void QQuickWebViewPrivate::loadProgressDidChange(int loadProgress)
392 {
393     Q_Q(QQuickWebView);
394
395     m_loadProgress = loadProgress;
396
397     emit q->loadProgressChanged();
398 }
399
400 void QQuickWebViewPrivate::backForwardListDidChange()
401 {
402     navigationHistory->d->reset();
403 }
404
405 void QQuickWebViewPrivate::loadDidSucceed()
406 {
407     Q_Q(QQuickWebView);
408     ASSERT(!q->loading());
409
410     QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadSucceededStatus);
411     emit q->loadingChanged(&loadRequest);
412 }
413
414 void QQuickWebViewPrivate::loadDidFail(const QtWebError& error)
415 {
416     Q_Q(QQuickWebView);
417     ASSERT(!q->loading());
418
419     QWebLoadRequest loadRequest(error.url(), QQuickWebView::LoadFailedStatus, error.description(), static_cast<QQuickWebView::ErrorDomain>(error.type()), error.errorCode());
420     emit q->loadingChanged(&loadRequest);
421 }
422
423 void QQuickWebViewPrivate::handleMouseEvent(QMouseEvent* event)
424 {
425     switch (event->type()) {
426     case QEvent::MouseButtonPress:
427         pageView->eventHandler()->handleMousePressEvent(event);
428         break;
429     case QEvent::MouseMove:
430         pageView->eventHandler()->handleMouseMoveEvent(event);
431         break;
432     case QEvent::MouseButtonRelease:
433         pageView->eventHandler()->handleMouseReleaseEvent(event);
434         break;
435     case QEvent::MouseButtonDblClick:
436         // If a MouseButtonDblClick was received then we got a MouseButtonPress before.
437         // WebCore will build double-clicks out of press events.
438         event->accept();
439         break;
440     default:
441         ASSERT_NOT_REACHED();
442         break;
443     }
444 }
445
446 void QQuickWebViewPrivate::setNeedsDisplay()
447 {
448     Q_Q(QQuickWebView);
449     if (renderToOffscreenBuffer()) {
450         // This is used only to mantain the rendering synchronisation between the UI and
451         // the web process when running tests even if the render loop is not active.
452         QImage dummyImage(1, 1, QImage::Format_ARGB32);
453         QPainter painter(&dummyImage);
454         q->page()->d->paint(&painter);
455         return;
456     }
457     q->page()->update();
458 }
459
460 void QQuickWebViewPrivate::didRenderFrame()
461 {
462     Q_Q(QQuickWebView);
463     if (m_betweenLoadCommitAndFirstFrame) {
464         emit q->experimental()->loadVisuallyCommitted();
465         m_betweenLoadCommitAndFirstFrame = false;
466     }
467 }
468
469 void QQuickWebViewPrivate::processDidCrash()
470 {
471     Q_Q(QQuickWebView);
472
473     QUrl url(KURL(WebCore::ParsedURLString, webPageProxy->urlAtProcessExit()));
474     qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(url.toString(QUrl::RemoveUserInfo)));
475
476     pageView->eventHandler()->resetGestureRecognizers();
477
478     // Check if loading was ongoing, when process crashed.
479     if (m_loadProgress > 0 && m_loadProgress < 100) {
480         QWebLoadRequest loadRequest(url, QQuickWebView::LoadFailedStatus, QLatin1String("The web process crashed."), QQuickWebView::InternalErrorDomain, 0);
481
482         loadProgressDidChange(100);
483         emit q->loadingChanged(&loadRequest);
484     }
485 }
486
487 void QQuickWebViewPrivate::didRelaunchProcess()
488 {
489     qWarning("WARNING: The web process has been successfully restarted.");
490
491     webPageProxy->drawingArea()->setSize(viewSize(), IntSize());
492
493     updateViewportSize();
494     updateUserScripts();
495 }
496
497 PassOwnPtr<DrawingAreaProxy> QQuickWebViewPrivate::createDrawingAreaProxy()
498 {
499     return DrawingAreaProxyImpl::create(webPageProxy.get());
500 }
501
502 void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download)
503 {
504     Q_Q(QQuickWebView);
505     // This function is responsible for hooking up a DownloadProxy to our API layer
506     // by creating a QWebDownloadItem. It will then wait for the QWebDownloadItem to be
507     // ready (filled with the ResourceResponse information) so we can pass it through to
508     // our WebViews.
509     QWebDownloadItem* downloadItem = new QWebDownloadItem();
510     downloadItem->d->downloadProxy = download;
511
512     q->connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), q, SLOT(_q_onReceivedResponseFromDownload(QWebDownloadItem*)));
513     QtWebContext::downloadManager()->addDownload(download, downloadItem);
514 }
515
516 void QQuickWebViewPrivate::_q_onVisibleChanged()
517 {
518     webPageProxy->viewStateDidChange(WebPageProxy::ViewIsVisible);
519 }
520
521 void QQuickWebViewPrivate::_q_onUrlChanged()
522 {
523     updateIcon();
524 }
525
526 void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QString& pageUrl)
527 {
528     if (pageUrl != QString(m_currentUrl))
529         return;
530
531     updateIcon();
532 }
533
534 /* Called either when the url changes, or when the icon for the current page changes */
535 void QQuickWebViewPrivate::updateIcon()
536 {
537     Q_Q(QQuickWebView);
538
539     QQuickView* view = qobject_cast<QQuickView*>(q->window());
540     if (!view)
541         return;
542
543     QWebIconImageProvider* provider = static_cast<QWebIconImageProvider*>(
544                 view->engine()->imageProvider(QWebIconImageProvider::identifier()));
545     if (!provider)
546         return;
547
548     WTF::String iconUrl = provider->iconURLForPageURLInContext(m_currentUrl, context.get());
549
550     if (iconUrl == m_iconUrl)
551         return;
552
553     m_iconUrl = iconUrl;
554     emit q->iconChanged();
555 }
556
557 void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* downloadItem)
558 {
559     // Now that our downloadItem has everything we need we can emit downloadRequested.
560     if (!downloadItem)
561         return;
562
563     Q_Q(QQuickWebView);
564     QQmlEngine::setObjectOwnership(downloadItem, QQmlEngine::JavaScriptOwnership);
565     emit q->experimental()->downloadRequested(downloadItem);
566 }
567
568 void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText)
569 {
570     Q_Q(QQuickWebView);
571     QtDialogRunner dialogRunner(q);
572     if (!dialogRunner.initForAlert(alertText))
573         return;
574
575     dialogRunner.run();
576 }
577
578 bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message)
579 {
580     Q_Q(QQuickWebView);
581     QtDialogRunner dialogRunner(q);
582     if (!dialogRunner.initForConfirm(message))
583         return true;
584
585     dialogRunner.run();
586
587     return dialogRunner.wasAccepted();
588 }
589
590 QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok)
591 {
592     Q_Q(QQuickWebView);
593     QtDialogRunner dialogRunner(q);
594     if (!dialogRunner.initForPrompt(message, defaultValue)) {
595         ok = true;
596         return defaultValue;
597     }
598
599     dialogRunner.run();
600
601     ok = dialogRunner.wasAccepted();
602     return dialogRunner.result();
603 }
604
605 void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password)
606 {
607     Q_Q(QQuickWebView);
608     QtDialogRunner dialogRunner(q);
609     if (!dialogRunner.initForAuthentication(hostname, realm, prefilledUsername))
610         return;
611
612     dialogRunner.run();
613
614     username = dialogRunner.username();
615     password = dialogRunner.password();
616 }
617
618 void QQuickWebViewPrivate::handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password)
619 {
620     Q_Q(QQuickWebView);
621     QtDialogRunner dialogRunner(q);
622     if (!dialogRunner.initForProxyAuthentication(hostname, port, prefilledUsername))
623         return;
624
625     dialogRunner.run();
626
627     username = dialogRunner.username();
628     password = dialogRunner.password();
629 }
630
631 bool QQuickWebViewPrivate::handleCertificateVerificationRequest(const QString& hostname)
632 {
633     Q_Q(QQuickWebView);
634
635     if (m_allowAnyHTTPSCertificateForLocalHost
636         && (hostname == QStringLiteral("127.0.0.1") || hostname == QStringLiteral("localhost")))
637         return true;
638
639     QtDialogRunner dialogRunner(q);
640     if (!dialogRunner.initForCertificateVerification(hostname))
641         return false;
642
643     dialogRunner.run();
644
645     return dialogRunner.wasAccepted();
646 }
647
648 void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type)
649 {
650     Q_Q(QQuickWebView);
651
652     QtDialogRunner dialogRunner(q);
653     if (!dialogRunner.initForFilePicker(selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection)))
654         return;
655
656     dialogRunner.run();
657
658     if (dialogRunner.wasAccepted()) {
659         QStringList selectedPaths = dialogRunner.filePaths();
660
661         Vector<RefPtr<APIObject> > wkFiles(selectedPaths.size());
662         for (unsigned i = 0; i < selectedPaths.size(); ++i)
663             wkFiles[i] = WebURL::create(QUrl::fromLocalFile(selectedPaths.at(i)).toString());            
664
665         WKOpenPanelResultListenerChooseFiles(listenerRef, toAPI(ImmutableArray::adopt(wkFiles).leakRef()));
666     } else
667         WKOpenPanelResultListenerCancel(listenerRef);
668
669 }
670
671 quint64 QQuickWebViewPrivate::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage)
672 {
673     Q_Q(QQuickWebView);
674     QtDialogRunner dialogRunner(q);
675     if (!dialogRunner.initForDatabaseQuotaDialog(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage))
676         return 0;
677
678     dialogRunner.run();
679
680     return dialogRunner.wasAccepted() ? dialogRunner.databaseQuota() : 0;
681 }
682
683 /* The 'WebView' attached property allows items spawned by the webView to
684    refer back to the originating webView through 'WebView.view', similar
685    to how ListView.view and GridView.view is exposed to items. */
686 QQuickWebViewAttached::QQuickWebViewAttached(QObject* object)
687     : QObject(object)
688     , m_view(0)
689 {
690 }
691
692 void QQuickWebViewAttached::setView(QQuickWebView* view)
693 {
694     if (m_view == view)
695         return;
696     m_view = view;
697     emit viewChanged();
698 }
699
700 QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object)
701 {
702     return new QQuickWebViewAttached(object);
703 }
704
705
706
707 void QQuickWebViewPrivate::addAttachedPropertyTo(QObject* object)
708 {
709     Q_Q(QQuickWebView);
710     QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object));
711     attached->setView(q);
712 }
713
714 bool QQuickWebViewPrivate::navigatorQtObjectEnabled() const
715 {
716     return m_navigatorQtObjectEnabled;
717 }
718
719 void QQuickWebViewPrivate::setNavigatorQtObjectEnabled(bool enabled)
720 {
721     ASSERT(enabled != m_navigatorQtObjectEnabled);
722     // FIXME: Currently we have to keep this information in both processes and the setting is asynchronous.
723     m_navigatorQtObjectEnabled = enabled;
724     context->setNavigatorQtObjectEnabled(webPageProxy.get(), enabled);
725 }
726
727 static QString readUserScript(const QUrl& url)
728 {
729     QString path;
730     if (url.isLocalFile())
731         path = url.toLocalFile();
732     else if (url.scheme() == QLatin1String("qrc"))
733         path = QStringLiteral(":") + url.path();
734     else {
735         qWarning("QQuickWebView: Couldn't open '%s' as user script because only file:/// and qrc:/// URLs are supported.", qPrintable(url.toString()));
736         return QString();
737     }
738
739     QFile file(path);
740     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
741         qWarning("QQuickWebView: Couldn't open '%s' as user script due to error '%s'.", qPrintable(url.toString()), qPrintable(file.errorString()));
742         return QString();
743     }
744
745     QString contents = QString::fromUtf8(file.readAll());
746     if (contents.isEmpty())
747         qWarning("QQuickWebView: Ignoring '%s' as user script because file is empty.", qPrintable(url.toString()));
748
749     return contents;
750 }
751
752 void QQuickWebViewPrivate::updateUserScripts()
753 {
754     Vector<String> scripts;
755     scripts.reserveCapacity(userScripts.size());
756
757     for (unsigned i = 0; i < userScripts.size(); ++i) {
758         const QUrl& url = userScripts.at(i);
759         if (!url.isValid()) {
760             qWarning("QQuickWebView: Couldn't open '%s' as user script because URL is invalid.", qPrintable(url.toString()));
761             continue;
762         }
763
764         QString contents = readUserScript(url);
765         if (contents.isEmpty())
766             continue;
767         scripts.append(String(contents));
768     }
769
770     webPageProxy->setUserScripts(scripts);
771 }
772
773 QPointF QQuickWebViewPrivate::contentPos() const
774 {
775     Q_Q(const QQuickWebView);
776     return QPointF(q->contentX(), q->contentY());
777 }
778
779 void QQuickWebViewPrivate::setContentPos(const QPointF& pos)
780 {
781     Q_Q(QQuickWebView);
782     q->setContentX(pos.x());
783     q->setContentY(pos.y());
784 }
785
786 WebCore::IntSize QQuickWebViewPrivate::viewSize() const
787 {
788     return WebCore::IntSize(pageView->width(), pageView->height());
789 }
790
791 /*!
792     \internal
793
794     \qmlsignal WebViewExperimental::onMessageReceived(var message)
795
796     \brief Emitted when JavaScript code executing on the web page calls navigator.qt.postMessage().
797
798     \sa postMessage
799 */
800 void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message)
801 {
802     QVariantMap variantMap;
803     variantMap.insert(QLatin1String("data"), QString(message));
804     variantMap.insert(QLatin1String("origin"), q_ptr->url());
805     emit q_ptr->experimental()->messageReceived(variantMap);
806 }
807
808 QQuickWebViewLegacyPrivate::QQuickWebViewLegacyPrivate(QQuickWebView* viewport)
809     : QQuickWebViewPrivate(viewport)
810 {
811 }
812
813 void QQuickWebViewLegacyPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
814 {
815     QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
816
817     // Trigger setting of correct visibility flags after everything was allocated and initialized.
818     _q_onVisibleChanged();
819 }
820
821 void QQuickWebViewLegacyPrivate::updateViewportSize()
822 {
823     Q_Q(QQuickWebView);
824     QSizeF viewportSize = q->boundingRect().size();
825     if (viewportSize.isEmpty())
826         return;
827
828     float devicePixelRatio = webPageProxy->deviceScaleFactor();
829     pageView->setContentsSize(viewportSize);
830     // Make sure that our scale matches the one passed to setVisibleContentsRect.
831     pageView->setContentsScale(devicePixelRatio);
832
833     // The fixed layout is handled by the FrameView and the drawing area doesn't behave differently
834     // whether its fixed or not. We still need to tell the drawing area which part of it
835     // has to be rendered on tiles, and in desktop mode it's all of it.
836     webPageProxy->drawingArea()->setSize((viewportSize / devicePixelRatio).toSize(), IntSize());
837     webPageProxy->drawingArea()->setVisibleContentsRect(FloatRect(FloatPoint(), FloatSize(viewportSize / devicePixelRatio)), devicePixelRatio, FloatPoint());
838 }
839
840 qreal QQuickWebViewLegacyPrivate::zoomFactor() const
841 {
842     return webPageProxy->pageZoomFactor();
843 }
844
845 void QQuickWebViewLegacyPrivate::setZoomFactor(qreal factor)
846 {
847     webPageProxy->setPageZoomFactor(factor);
848 }
849
850 QQuickWebViewFlickablePrivate::QQuickWebViewFlickablePrivate(QQuickWebView* viewport)
851     : QQuickWebViewPrivate(viewport)
852 {
853 }
854
855 void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
856 {
857     QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
858 }
859
860 void QQuickWebViewFlickablePrivate::onComponentComplete()
861 {
862     QQuickWebViewPrivate::onComponentComplete();
863
864     Q_Q(QQuickWebView);
865     m_pageViewportControllerClient.reset(new PageViewportControllerClientQt(q, pageView.data()));
866     m_pageViewportController.reset(new PageViewportController(webPageProxy.get(), m_pageViewportControllerClient.data()));
867     pageView->eventHandler()->setViewportController(m_pageViewportControllerClient.data());
868
869     // Trigger setting of correct visibility flags after everything was allocated and initialized.
870     _q_onVisibleChanged();
871 }
872
873 void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& newAttributes)
874 {
875     if (m_pageViewportController)
876         m_pageViewportController->didChangeViewportAttributes(newAttributes);
877 }
878
879 void QQuickWebViewFlickablePrivate::updateViewportSize()
880 {
881     Q_Q(QQuickWebView);
882
883     if (m_pageViewportController)
884         m_pageViewportController->didChangeViewportSize(FloatSize(q->width(), q->height()));
885 }
886
887 void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos)
888 {
889     if (m_pageViewportController)
890         m_pageViewportController->pageDidRequestScroll(pos);
891 }
892
893 QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView, QQuickWebViewPrivate* webViewPrivate)
894     : QObject(webView)
895     , q_ptr(webView)
896     , d_ptr(webViewPrivate)
897     , schemeParent(new QObject(this))
898     , m_test(new QWebKitTest(webViewPrivate, this))
899 {
900 }
901
902 QQuickWebViewExperimental::~QQuickWebViewExperimental()
903 {
904 }
905
906 void QQuickWebViewExperimental::setRenderToOffscreenBuffer(bool enable)
907 {
908     Q_D(QQuickWebView);
909     d->setRenderToOffscreenBuffer(enable);
910 }
911
912 bool QQuickWebViewExperimental::renderToOffscreenBuffer() const
913 {
914     Q_D(const QQuickWebView);
915     return d->renderToOffscreenBuffer();
916 }
917
918 bool QQuickWebViewExperimental::transparentBackground() const
919 {
920     Q_D(const QQuickWebView);
921     return d->transparentBackground();
922 }
923 void QQuickWebViewExperimental::setTransparentBackground(bool enable)
924 {
925     Q_D(QQuickWebView);
926     d->setTransparentBackground(enable);
927 }
928
929 bool QQuickWebViewExperimental::useDefaultContentItemSize() const
930 {
931     Q_D(const QQuickWebView);
932     return d->m_useDefaultContentItemSize;
933 }
934
935 void QQuickWebViewExperimental::setUseDefaultContentItemSize(bool enable)
936 {
937     Q_D(QQuickWebView);
938     d->m_useDefaultContentItemSize = enable;
939 }
940
941 /*!
942     \internal
943
944     \qmlproperty int WebViewExperimental::preferredMinimumContentsWidth
945     \brief Minimum contents width when not overriden by the page itself.
946
947     Unless the page defines how contents should be laid out, using e.g.
948     the viewport meta tag, it is laid out given the width of the viewport
949     (in CSS units).
950
951     This setting can be used to enforce a minimum width when the page
952     does not define a width itself. This is useful for laying out pages
953     designed for big screens, commonly knows as desktop pages, on small
954     devices.
955
956     The default value is 0, but the value of 980 is recommented for small
957     screens as it provides a good trade off between legitable pages and
958     non-broken content.
959  */
960 int QQuickWebViewExperimental::preferredMinimumContentsWidth() const
961 {
962     Q_D(const QQuickWebView);
963     return d->webPageProxy->pageGroup()->preferences()->layoutFallbackWidth();
964 }
965
966 void QQuickWebViewExperimental::setPreferredMinimumContentsWidth(int width)
967 {
968     Q_D(QQuickWebView);
969     WebPreferences* webPreferences = d->webPageProxy->pageGroup()->preferences();
970
971     if (width == webPreferences->layoutFallbackWidth())
972         return;
973
974     webPreferences->setLayoutFallbackWidth(width);
975     emit preferredMinimumContentsWidthChanged();
976 }
977
978 void QQuickWebViewExperimental::setFlickableViewportEnabled(bool enable)
979 {
980     s_flickableViewportEnabled = enable;
981 }
982
983 bool QQuickWebViewExperimental::flickableViewportEnabled()
984 {
985     return s_flickableViewportEnabled;
986 }
987
988 /*!
989     \internal
990
991     \qmlmethod void WebViewExperimental::postMessage(string message)
992
993     \brief Post a message to an onmessage function registered with the navigator.qt object
994            by JavaScript code executing on the page.
995
996     \sa onMessageReceived
997 */
998
999 void QQuickWebViewExperimental::postMessage(const QString& message)
1000 {
1001     Q_D(QQuickWebView);
1002     d->context->postMessageToNavigatorQtObject(d->webPageProxy.get(), message);
1003 }
1004
1005 QQmlComponent* QQuickWebViewExperimental::alertDialog() const
1006 {
1007     Q_D(const QQuickWebView);
1008     return d->alertDialog;
1009 }
1010
1011 void QQuickWebViewExperimental::setAlertDialog(QQmlComponent* alertDialog)
1012 {
1013     Q_D(QQuickWebView);
1014     if (d->alertDialog == alertDialog)
1015         return;
1016     d->alertDialog = alertDialog;
1017     emit alertDialogChanged();
1018 }
1019
1020 QQmlComponent* QQuickWebViewExperimental::confirmDialog() const
1021 {
1022     Q_D(const QQuickWebView);
1023     return d->confirmDialog;
1024 }
1025
1026 void QQuickWebViewExperimental::setConfirmDialog(QQmlComponent* confirmDialog)
1027 {
1028     Q_D(QQuickWebView);
1029     if (d->confirmDialog == confirmDialog)
1030         return;
1031     d->confirmDialog = confirmDialog;
1032     emit confirmDialogChanged();
1033 }
1034
1035 QWebNavigationHistory* QQuickWebViewExperimental::navigationHistory() const
1036 {
1037     return d_ptr->navigationHistory.get();
1038 }
1039
1040 QQmlComponent* QQuickWebViewExperimental::promptDialog() const
1041 {
1042     Q_D(const QQuickWebView);
1043     return d->promptDialog;
1044 }
1045
1046 QWebPreferences* QQuickWebViewExperimental::preferences() const
1047 {
1048     QQuickWebViewPrivate* const d = d_ptr;
1049     if (!d->preferences)
1050         d->preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(d));
1051     return d->preferences.get();
1052 }
1053
1054 void QQuickWebViewExperimental::setPromptDialog(QQmlComponent* promptDialog)
1055 {
1056     Q_D(QQuickWebView);
1057     if (d->promptDialog == promptDialog)
1058         return;
1059     d->promptDialog = promptDialog;
1060     emit promptDialogChanged();
1061 }
1062
1063 QQmlComponent* QQuickWebViewExperimental::authenticationDialog() const
1064 {
1065     Q_D(const QQuickWebView);
1066     return d->authenticationDialog;
1067 }
1068
1069 void QQuickWebViewExperimental::setAuthenticationDialog(QQmlComponent* authenticationDialog)
1070 {
1071     Q_D(QQuickWebView);
1072     if (d->authenticationDialog == authenticationDialog)
1073         return;
1074     d->authenticationDialog = authenticationDialog;
1075     emit authenticationDialogChanged();
1076 }
1077
1078 QQmlComponent* QQuickWebViewExperimental::proxyAuthenticationDialog() const
1079 {
1080     Q_D(const QQuickWebView);
1081     return d->proxyAuthenticationDialog;
1082 }
1083
1084 void QQuickWebViewExperimental::setProxyAuthenticationDialog(QQmlComponent* proxyAuthenticationDialog)
1085 {
1086     Q_D(QQuickWebView);
1087     if (d->proxyAuthenticationDialog == proxyAuthenticationDialog)
1088         return;
1089     d->proxyAuthenticationDialog = proxyAuthenticationDialog;
1090     emit proxyAuthenticationDialogChanged();
1091 }
1092 QQmlComponent* QQuickWebViewExperimental::certificateVerificationDialog() const
1093 {
1094     Q_D(const QQuickWebView);
1095     return d->certificateVerificationDialog;
1096 }
1097
1098 void QQuickWebViewExperimental::setCertificateVerificationDialog(QQmlComponent* certificateVerificationDialog)
1099 {
1100     Q_D(QQuickWebView);
1101     if (d->certificateVerificationDialog == certificateVerificationDialog)
1102         return;
1103     d->certificateVerificationDialog = certificateVerificationDialog;
1104     emit certificateVerificationDialogChanged();
1105 }
1106
1107 QQmlComponent* QQuickWebViewExperimental::itemSelector() const
1108 {
1109     Q_D(const QQuickWebView);
1110     return d->itemSelector;
1111 }
1112
1113 void QQuickWebViewExperimental::setItemSelector(QQmlComponent* itemSelector)
1114 {
1115     Q_D(QQuickWebView);
1116     if (d->itemSelector == itemSelector)
1117         return;
1118     d->itemSelector = itemSelector;
1119     emit itemSelectorChanged();
1120 }
1121
1122 QQmlComponent* QQuickWebViewExperimental::filePicker() const
1123 {
1124     Q_D(const QQuickWebView);
1125     return d->filePicker;
1126 }
1127
1128 void QQuickWebViewExperimental::setFilePicker(QQmlComponent* filePicker)
1129 {
1130     Q_D(QQuickWebView);
1131     if (d->filePicker == filePicker)
1132         return;
1133     d->filePicker = filePicker;
1134     emit filePickerChanged();
1135 }
1136
1137 QQmlComponent* QQuickWebViewExperimental::databaseQuotaDialog() const
1138 {
1139     Q_D(const QQuickWebView);
1140     return d->databaseQuotaDialog;
1141 }
1142
1143 void QQuickWebViewExperimental::setDatabaseQuotaDialog(QQmlComponent* databaseQuotaDialog)
1144 {
1145     Q_D(QQuickWebView);
1146     if (d->databaseQuotaDialog == databaseQuotaDialog)
1147         return;
1148     d->databaseQuotaDialog = databaseQuotaDialog;
1149     emit databaseQuotaDialogChanged();
1150 }
1151
1152 QQmlComponent* QQuickWebViewExperimental::colorChooser() const
1153 {
1154     Q_D(const QQuickWebView);
1155     return d->colorChooser;
1156 }
1157
1158 void QQuickWebViewExperimental::setColorChooser(QQmlComponent* colorChooser)
1159 {
1160     Q_D(QQuickWebView);
1161     if (d->colorChooser == colorChooser)
1162         return;
1163
1164     d->colorChooser = colorChooser;
1165     emit colorChooserChanged();
1166 }
1167
1168 QString QQuickWebViewExperimental::userAgent() const
1169 {
1170     Q_D(const QQuickWebView);
1171     return d->webPageProxy->userAgent();
1172 }
1173
1174 void QQuickWebViewExperimental::setUserAgent(const QString& userAgent)
1175 {
1176     Q_D(QQuickWebView);
1177     if (userAgent == QString(d->webPageProxy->userAgent()))
1178         return;
1179
1180     d->webPageProxy->setUserAgent(userAgent);
1181     emit userAgentChanged();
1182 }
1183
1184 /*!
1185     \internal
1186
1187     \qmlproperty real WebViewExperimental::devicePixelRatio
1188     \brief The ratio between the CSS units and device pixels when the content is unscaled.
1189
1190     When designing touch-friendly contents, knowing the approximated target size on a device
1191     is important for contents providers in order to get the intented layout and element
1192     sizes.
1193
1194     As most first generation touch devices had a PPI of approximately 160, this became a
1195     de-facto value, when used in conjunction with the viewport meta tag.
1196
1197     Devices with a higher PPI learning towards 240 or 320, applies a pre-scaling on all
1198     content, of either 1.5 or 2.0, not affecting the CSS scale or pinch zooming.
1199
1200     This value can be set using this property and it is exposed to CSS media queries using
1201     the -webkit-device-pixel-ratio query.
1202
1203     For instance, if you want to load an image without having it upscaled on a web view
1204     using a device pixel ratio of 2.0 it can be done by loading an image of say 100x100
1205     pixels but showing it at half the size.
1206
1207     FIXME: Move documentation example out in separate files
1208
1209     @media (-webkit-min-device-pixel-ratio: 1.5) {
1210         .icon {
1211             width: 50px;
1212             height: 50px;
1213             url: "/images/icon@2x.png"; // This is actually a 100x100 image
1214         }
1215     }
1216
1217     If the above is used on a device with device pixel ratio of 1.5, it will be scaled
1218     down but still provide a better looking image.
1219 */
1220
1221 qreal QQuickWebViewExperimental::devicePixelRatio() const
1222 {
1223     Q_D(const QQuickWebView);
1224     return d->webPageProxy->deviceScaleFactor();
1225 }
1226
1227 void QQuickWebViewExperimental::setDevicePixelRatio(qreal devicePixelRatio)
1228 {
1229     Q_D(QQuickWebView);
1230     if (0 >= devicePixelRatio || devicePixelRatio == this->devicePixelRatio())
1231         return;
1232
1233     d->webPageProxy->setIntrinsicDeviceScaleFactor(devicePixelRatio);
1234     emit devicePixelRatioChanged();
1235 }
1236
1237 /*!
1238     \internal
1239
1240     \qmlproperty int WebViewExperimental::deviceWidth
1241     \brief The device width used by the viewport calculations.
1242
1243     The value used when calculation the viewport, eg. what is used for 'device-width' when
1244     used in the viewport meta tag. If unset (zero or negative width), the width of the
1245     actual viewport is used instead.
1246 */
1247
1248 int QQuickWebViewExperimental::deviceWidth() const
1249 {
1250     Q_D(const QQuickWebView);
1251     return d->webPageProxy->pageGroup()->preferences()->deviceWidth();
1252 }
1253
1254 void QQuickWebViewExperimental::setDeviceWidth(int value)
1255 {
1256     Q_D(QQuickWebView);
1257     d->webPageProxy->pageGroup()->preferences()->setDeviceWidth(qMax(0, value));
1258     emit deviceWidthChanged();
1259 }
1260
1261 /*!
1262     \internal
1263
1264     \qmlproperty int WebViewExperimental::deviceHeight
1265     \brief The device width used by the viewport calculations.
1266
1267     The value used when calculation the viewport, eg. what is used for 'device-height' when
1268     used in the viewport meta tag. If unset (zero or negative height), the height of the
1269     actual viewport is used instead.
1270 */
1271
1272 int QQuickWebViewExperimental::deviceHeight() const
1273 {
1274     Q_D(const QQuickWebView);
1275     return d->webPageProxy->pageGroup()->preferences()->deviceHeight();
1276 }
1277
1278 void QQuickWebViewExperimental::setDeviceHeight(int value)
1279 {
1280     Q_D(QQuickWebView);
1281     d->webPageProxy->pageGroup()->preferences()->setDeviceHeight(qMax(0, value));
1282     emit deviceHeightChanged();
1283 }
1284
1285 /*!
1286     \internal
1287
1288     \qmlmethod void WebViewExperimental::evaluateJavaScript(string script [, function(result)])
1289
1290     \brief Evaluates the specified JavaScript and, if supplied, calls a function with the result.
1291 */
1292
1293 void QQuickWebViewExperimental::evaluateJavaScript(const QString& script, const QJSValue& value)
1294 {
1295     JSCallbackClosure* closure = new JSCallbackClosure;
1296
1297     closure->receiver = this;
1298     closure->value = value;
1299
1300     d_ptr->webPageProxy.get()->runJavaScriptInMainFrame(script, ScriptValueCallback::create(closure, javaScriptCallback));
1301 }
1302
1303 QList<QUrl> QQuickWebViewExperimental::userScripts() const
1304 {
1305     Q_D(const QQuickWebView);
1306     return d->userScripts;
1307 }
1308
1309 void QQuickWebViewExperimental::setUserScripts(const QList<QUrl>& userScripts)
1310 {
1311     Q_D(QQuickWebView);
1312     if (d->userScripts == userScripts)
1313         return;
1314     d->userScripts = userScripts;
1315     d->updateUserScripts();
1316     emit userScriptsChanged();
1317 }
1318
1319 QUrl QQuickWebViewExperimental::remoteInspectorUrl() const
1320 {
1321 #if ENABLE(INSPECTOR_SERVER)
1322     return QUrl(WebInspectorServer::shared().inspectorUrlForPageID(d_ptr->webPageProxy->inspector()->remoteInspectionPageID()));
1323 #else
1324     return QUrl();
1325 #endif
1326 }
1327
1328 QQuickUrlSchemeDelegate* QQuickWebViewExperimental::schemeDelegates_At(QQmlListProperty<QQuickUrlSchemeDelegate>* property, int index)
1329 {
1330     const QObjectList children = property->object->children();
1331     if (index < children.count())
1332         return static_cast<QQuickUrlSchemeDelegate*>(children.at(index));
1333     return 0;
1334 }
1335
1336 void QQuickWebViewExperimental::schemeDelegates_Append(QQmlListProperty<QQuickUrlSchemeDelegate>* property, QQuickUrlSchemeDelegate *scheme)
1337 {
1338     QObject* schemeParent = property->object;
1339     scheme->setParent(schemeParent);
1340     QQuickWebViewExperimental* webViewExperimental = qobject_cast<QQuickWebViewExperimental*>(property->object->parent());
1341     if (!webViewExperimental)
1342         return;
1343     scheme->reply()->setWebViewExperimental(webViewExperimental);
1344     QQuickWebViewPrivate* d = webViewExperimental->d_func();
1345     d->webPageProxy->registerApplicationScheme(scheme->scheme());
1346 }
1347
1348 int QQuickWebViewExperimental::schemeDelegates_Count(QQmlListProperty<QQuickUrlSchemeDelegate>* property)
1349 {
1350     return property->object->children().count();
1351 }
1352
1353 void QQuickWebViewExperimental::schemeDelegates_Clear(QQmlListProperty<QQuickUrlSchemeDelegate>* property)
1354 {
1355     const QObjectList children = property->object->children();
1356     for (int index = 0; index < children.count(); index++) {
1357         QObject* child = children.at(index);
1358         child->setParent(0);
1359         delete child;
1360     }
1361 }
1362
1363 QQmlListProperty<QQuickUrlSchemeDelegate> QQuickWebViewExperimental::schemeDelegates()
1364 {
1365     return QQmlListProperty<QQuickUrlSchemeDelegate>(schemeParent, 0,
1366             QQuickWebViewExperimental::schemeDelegates_Append,
1367             QQuickWebViewExperimental::schemeDelegates_Count,
1368             QQuickWebViewExperimental::schemeDelegates_At,
1369             QQuickWebViewExperimental::schemeDelegates_Clear);
1370 }
1371
1372 void QQuickWebViewExperimental::invokeApplicationSchemeHandler(PassRefPtr<QtRefCountedNetworkRequestData> request)
1373 {
1374     RefPtr<QtRefCountedNetworkRequestData> req = request;
1375     const QObjectList children = schemeParent->children();
1376     for (int index = 0; index < children.count(); index++) {
1377         QQuickUrlSchemeDelegate* delegate = qobject_cast<QQuickUrlSchemeDelegate*>(children.at(index));
1378         if (!delegate)
1379             continue;
1380         if (!delegate->scheme().compare(QString(req->data().m_scheme), Qt::CaseInsensitive)) {
1381             delegate->request()->setNetworkRequestData(req);
1382             delegate->reply()->setNetworkRequestData(req);
1383             emit delegate->receivedRequest();
1384             return;
1385         }
1386     }
1387 }
1388
1389 void QQuickWebViewExperimental::sendApplicationSchemeReply(QQuickNetworkReply* reply)
1390 {
1391     d_ptr->webPageProxy->sendApplicationSchemeReply(reply);
1392 }
1393
1394 void QQuickWebViewExperimental::goForwardTo(int index)
1395 {
1396     d_ptr->navigationHistory->d->goForwardTo(index);
1397 }
1398
1399 void QQuickWebViewExperimental::goBackTo(int index)
1400 {
1401     d_ptr->navigationHistory->d->goBackTo(index);
1402 }
1403
1404 QWebKitTest* QQuickWebViewExperimental::test()
1405 {
1406     return m_test;
1407 }
1408
1409 QQuickWebPage* QQuickWebViewExperimental::page()
1410 {
1411     return q_ptr->page();
1412 }
1413
1414 /*!
1415     \page index.html
1416     \title QtWebKit: QML WebView version 3.0
1417
1418     The WebView API allows QML applications to render regions of dynamic
1419     web content. A \e{WebView} component may share the screen with other
1420     QML components or encompass the full screen as specified within the
1421     QML application.
1422
1423     QML WebView version 3.0 is incompatible with previous QML \l
1424     {QtWebKit1::WebView} {WebView} API versions.  It allows an
1425     application to load pages into the WebView, either by URL or with
1426     an HTML string, and navigate within session history.  By default,
1427     links to different pages load within the same WebView, but applications
1428     may intercept requests to delegate links to other functions.
1429
1430     This sample QML application loads a web page, responds to session
1431     history context, and intercepts requests for external links:
1432
1433     \code
1434     import QtQuick 2.0
1435     import QtWebKit 3.0
1436
1437     Page {
1438         WebView {
1439             id: webview
1440             url: "http://qt-project.org"
1441             width: parent.width
1442             height: parent.height
1443             onNavigationRequested: {
1444                 // detect URL scheme prefix, most likely an external link
1445                 var schemaRE = /^\w+:/;
1446                 if (schemaRE.test(request.url)) {
1447                     request.action = WebView.AcceptRequest;
1448                 } else {
1449                     request.action = WebView.IgnoreRequest;
1450                     // delegate request.url here
1451                 }
1452             }
1453         }
1454     }
1455     \endcode
1456 */
1457
1458
1459 /*!
1460     \qmltype WebView
1461     \instantiates QQuickWebView
1462     \inqmlmodule QtWebKit 3.0
1463     \brief A WebView renders web content within a QML application
1464 */
1465
1466 QQuickWebView::QQuickWebView(QQuickItem* parent)
1467     : QQuickFlickable(parent)
1468     , d_ptr(createPrivateObject(this))
1469 {
1470     Q_D(QQuickWebView);
1471     d->initialize();
1472 }
1473
1474 QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent)
1475     : QQuickFlickable(parent)
1476     , d_ptr(createPrivateObject(this))
1477 {
1478     Q_D(QQuickWebView);
1479     d->initialize(contextRef, pageGroupRef);
1480 }
1481
1482 QQuickWebView::~QQuickWebView()
1483 {
1484 }
1485
1486 QQuickWebPage* QQuickWebView::page()
1487 {
1488     Q_D(QQuickWebView);
1489     return d->pageView.data();
1490 }
1491
1492 /*!
1493     \qmlmethod void WebView::goBack()
1494
1495     Go backward within the browser's session history, if possible.
1496     (Equivalent to the \c{window.history.back()} DOM method.)
1497
1498     \sa WebView::canGoBack
1499 */
1500 void QQuickWebView::goBack()
1501 {
1502     Q_D(QQuickWebView);
1503     d->webPageProxy->goBack();
1504 }
1505
1506 /*!
1507     \qmlmethod void WebView::goForward()
1508
1509     Go forward within the browser's session history, if possible.
1510     (Equivalent to the \c{window.history.forward()} DOM method.)
1511 */
1512 void QQuickWebView::goForward()
1513 {
1514     Q_D(QQuickWebView);
1515     d->webPageProxy->goForward();
1516 }
1517
1518 /*!
1519     \qmlmethod void WebView::stop()
1520
1521     Stop loading the current page.
1522 */
1523 void QQuickWebView::stop()
1524 {
1525     Q_D(QQuickWebView);
1526     d->webPageProxy->stopLoading();
1527 }
1528
1529 /*!
1530     \qmlmethod void WebView::reload()
1531
1532     Reload the current page. (Equivalent to the
1533     \c{window.location.reload()} DOM method.)
1534 */
1535 void QQuickWebView::reload()
1536 {
1537     Q_D(QQuickWebView);
1538
1539     WebFrameProxy* mainFrame = d->webPageProxy->mainFrame();
1540     if (mainFrame && !mainFrame->unreachableURL().isEmpty() && mainFrame->url() != blankURL()) {
1541         // We are aware of the unreachable url on the UI process side, but since we haven't
1542         // loaded alternative/subsitute data for it (an error page eg.) WebCore doesn't know
1543         // about the unreachable url yet. If we just do a reload at this point WebCore will try to
1544         // reload the currently committed url instead of the unrachable url. To work around this
1545         // we override the reload here by doing a manual load.
1546         d->webPageProxy->loadURL(mainFrame->unreachableURL());
1547         // FIXME: We should make WebCore aware of the unreachable url regardless of substitute-loads
1548         return;
1549     }
1550
1551     const bool reloadFromOrigin = true;
1552     d->webPageProxy->reload(reloadFromOrigin);
1553 }
1554
1555 /*!
1556     \qmlproperty url WebView::url
1557
1558     The location of the currently displaying HTML page. This writable
1559     property offers the main interface to load a page into a web view.
1560     It functions the same as the \c{window.location} DOM property.
1561
1562     \sa WebView::loadHtml()
1563 */
1564 QUrl QQuickWebView::url() const
1565 {
1566     Q_D(const QQuickWebView);
1567
1568     // FIXME: Enable once we are sure this should not trigger
1569     // Q_ASSERT(d->m_currentUrl == d->webPageProxy->activeURL());
1570
1571     return QUrl(d->m_currentUrl);
1572 }
1573
1574 void QQuickWebView::setUrl(const QUrl& url)
1575 {
1576     Q_D(QQuickWebView);
1577
1578     if (url.isEmpty())
1579         return;
1580
1581     d->webPageProxy->loadURL(url.toString());
1582     emitUrlChangeIfNeeded();
1583 }
1584
1585 // Make sure we don't emit urlChanged unless it actually changed
1586 void QQuickWebView::emitUrlChangeIfNeeded()
1587 {
1588     Q_D(QQuickWebView);
1589
1590     WTF::String activeUrl = d->webPageProxy->activeURL();
1591     if (activeUrl != d->m_currentUrl) {
1592         d->m_currentUrl = activeUrl;
1593         emit urlChanged();
1594     }
1595 }
1596
1597 /*!
1598     \qmlproperty url WebView::icon
1599
1600     The location of the currently displaying Web site icon, also known as favicon
1601     or shortcut icon. This read-only URL corresponds to the image used within a
1602     mobile browser application to represent a bookmarked page on the device's home
1603     screen.
1604
1605     This example uses the \c{icon} property to build an \c{Image} element:
1606
1607     \code
1608     Image {
1609         id: appIcon
1610         source: webView.icon != "" ? webView.icon : "fallbackFavIcon.png";
1611         ...
1612     }
1613     \endcode
1614 */
1615 QUrl QQuickWebView::icon() const
1616 {
1617     Q_D(const QQuickWebView);
1618     return QUrl(d->m_iconUrl);
1619 }
1620
1621 /*!
1622     \qmlproperty int WebView::loadProgress
1623
1624     The amount of the page that has been loaded, expressed as an integer
1625     percentage in the range from \c{0} to \c{100}.
1626 */
1627 int QQuickWebView::loadProgress() const
1628 {
1629     Q_D(const QQuickWebView);
1630     return d->loadProgress();
1631 }
1632
1633 /*!
1634     \qmlproperty bool WebView::canGoBack
1635
1636     Returns \c{true} if there are prior session history entries, \c{false}
1637     otherwise.
1638 */
1639 bool QQuickWebView::canGoBack() const
1640 {
1641     Q_D(const QQuickWebView);
1642     return d->webPageProxy->canGoBack();
1643 }
1644
1645 /*!
1646     \qmlproperty bool WebView::canGoForward
1647
1648     Returns \c{true} if there are subsequent session history entries,
1649     \c{false} otherwise.
1650 */
1651 bool QQuickWebView::canGoForward() const
1652 {
1653     Q_D(const QQuickWebView);
1654     return d->webPageProxy->canGoForward();
1655 }
1656
1657 /*!
1658     \qmlproperty bool WebView::loading
1659
1660     Returns \c{true} if the HTML page is currently loading, \c{false} otherwise.
1661 */
1662 bool QQuickWebView::loading() const
1663 {
1664     Q_D(const QQuickWebView);
1665     RefPtr<WebKit::WebFrameProxy> mainFrame = d->webPageProxy->mainFrame();
1666     return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
1667 }
1668
1669 /*!
1670     \internal
1671  */
1672
1673 QPointF QQuickWebView::mapToWebContent(const QPointF& pointInViewCoordinates) const
1674 {
1675     Q_D(const QQuickWebView);
1676     return d->pageView->transformFromItem().map(pointInViewCoordinates);
1677 }
1678
1679 /*!
1680     \internal
1681  */
1682
1683 QRectF QQuickWebView::mapRectToWebContent(const QRectF& rectInViewCoordinates) const
1684 {
1685     Q_D(const QQuickWebView);
1686     return d->pageView->transformFromItem().mapRect(rectInViewCoordinates);
1687 }
1688
1689 /*!
1690     \internal
1691  */
1692
1693 QPointF QQuickWebView::mapFromWebContent(const QPointF& pointInCSSCoordinates) const
1694 {
1695     Q_D(const QQuickWebView);
1696     return d->pageView->transformToItem().map(pointInCSSCoordinates);
1697 }
1698
1699 /*!
1700     \internal
1701  */
1702 QRectF QQuickWebView::mapRectFromWebContent(const QRectF& rectInCSSCoordinates) const
1703 {
1704     Q_D(const QQuickWebView);
1705     return d->pageView->transformToItem().mapRect(rectInCSSCoordinates);
1706 }
1707
1708 /*!
1709     \qmlproperty string WebView::title
1710
1711     The title of the currently displaying HTML page, a read-only value
1712     that reflects the contents of the \c{<title>} tag.
1713 */
1714 QString QQuickWebView::title() const
1715 {
1716     Q_D(const QQuickWebView);
1717     return d->webPageProxy->pageTitle();
1718 }
1719
1720 QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const
1721 {
1722     Q_D(const QQuickWebView);
1723     const EditorState& state = d->webPageProxy->editorState();
1724
1725     switch(property) {
1726     case Qt::ImCursorRectangle:
1727         return QRectF(state.cursorRect);
1728     case Qt::ImFont:
1729         return QVariant();
1730     case Qt::ImCursorPosition:
1731         return QVariant(static_cast<int>(state.cursorPosition));
1732     case Qt::ImAnchorPosition:
1733         return QVariant(static_cast<int>(state.anchorPosition));
1734     case Qt::ImSurroundingText:
1735         return QString(state.surroundingText);
1736     case Qt::ImCurrentSelection:
1737         return QString(state.selectedText);
1738     case Qt::ImMaximumTextLength:
1739         return QVariant(); // No limit.
1740     case Qt::ImHints:
1741         return int(Qt::InputMethodHints(state.inputMethodHints));
1742     default:
1743         // Rely on the base implementation for ImEnabled, ImHints and ImPreferredLanguage.
1744         return QQuickFlickable::inputMethodQuery(property);
1745     }
1746 }
1747
1748 /*!
1749     internal
1750
1751     The experimental module consisting on experimental API which will break
1752     from version to version.
1753 */
1754 QQuickWebViewExperimental* QQuickWebView::experimental() const
1755 {
1756     Q_D(const QQuickWebView);
1757     return d->experimental;
1758 }
1759
1760 /*!
1761     \internal
1762 */
1763 void QQuickWebView::platformInitialize()
1764 {
1765     JSC::initializeThreading();
1766     WTF::initializeMainThread();
1767 }
1768
1769 bool QQuickWebView::childMouseEventFilter(QQuickItem* item, QEvent* event)
1770 {
1771     if (!isVisible() || !isEnabled())
1772         return false;
1773
1774     // This function is used by MultiPointTouchArea and PinchArea to filter
1775     // touch events, thus to hinder the canvas from sending synthesized
1776     // mouse events to the Flickable implementation we need to reimplement
1777     // childMouseEventFilter to ignore touch and mouse events.
1778
1779     switch (event->type()) {
1780     case QEvent::MouseButtonPress:
1781     case QEvent::MouseMove:
1782     case QEvent::MouseButtonRelease:
1783     case QEvent::TouchBegin:
1784     case QEvent::TouchUpdate:
1785     case QEvent::TouchEnd:
1786         // Force all mouse and touch events through the default propagation path.
1787         return false;
1788     default:
1789         ASSERT(event->type() == QEvent::UngrabMouse);
1790         break;
1791     }
1792
1793     return QQuickFlickable::childMouseEventFilter(item, event);
1794 }
1795
1796 void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
1797 {
1798     Q_D(QQuickWebView);
1799     QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
1800     if (newGeometry.size() != oldGeometry.size())
1801         d->updateViewportSize();
1802 }
1803
1804 void QQuickWebView::componentComplete()
1805 {
1806     Q_D(QQuickWebView);
1807     QQuickFlickable::componentComplete();
1808
1809     d->onComponentComplete();
1810     d->updateViewportSize();
1811 }
1812
1813 void QQuickWebView::keyPressEvent(QKeyEvent* event)
1814 {
1815     Q_D(QQuickWebView);
1816     d->pageView->eventHandler()->handleKeyPressEvent(event);
1817 }
1818
1819 void QQuickWebView::keyReleaseEvent(QKeyEvent* event)
1820 {
1821     Q_D(QQuickWebView);
1822     d->pageView->eventHandler()->handleKeyReleaseEvent(event);
1823 }
1824
1825 void QQuickWebView::inputMethodEvent(QInputMethodEvent* event)
1826 {
1827     Q_D(QQuickWebView);
1828     d->pageView->eventHandler()->handleInputMethodEvent(event);
1829 }
1830
1831 void QQuickWebView::focusInEvent(QFocusEvent* event)
1832 {
1833     Q_D(QQuickWebView);
1834     d->pageView->eventHandler()->handleFocusInEvent(event);
1835 }
1836
1837 void QQuickWebView::itemChange(ItemChange change, const ItemChangeData &value)
1838 {
1839     Q_D(QQuickWebView);
1840     if (change == ItemActiveFocusHasChanged) {
1841         bool focus = value.boolValue;
1842         if (!focus)
1843             d->pageView->eventHandler()->handleFocusLost();
1844     }
1845     QQuickFlickable::itemChange(change, value);
1846 }
1847
1848 void QQuickWebView::touchEvent(QTouchEvent* event)
1849 {
1850     Q_D(QQuickWebView);
1851
1852     bool lockingDisabled = flickableDirection() != AutoFlickDirection
1853                            || event->touchPoints().size() != 1
1854                            || width() >= contentWidth()
1855                            || height() >= contentHeight();
1856
1857     if (!lockingDisabled)
1858         d->axisLocker.update(event);
1859     else
1860         d->axisLocker.reset();
1861
1862     forceActiveFocus();
1863     d->pageView->eventHandler()->handleTouchEvent(event);
1864 }
1865
1866 void QQuickWebView::mousePressEvent(QMouseEvent* event)
1867 {
1868     Q_D(QQuickWebView);
1869     forceActiveFocus();
1870     d->handleMouseEvent(event);
1871 }
1872
1873 void QQuickWebView::mouseMoveEvent(QMouseEvent* event)
1874 {
1875     Q_D(QQuickWebView);
1876     d->handleMouseEvent(event);
1877 }
1878
1879 void QQuickWebView::mouseReleaseEvent(QMouseEvent* event)
1880 {
1881     Q_D(QQuickWebView);
1882     d->handleMouseEvent(event);
1883 }
1884
1885 void QQuickWebView::mouseDoubleClickEvent(QMouseEvent* event)
1886 {
1887     Q_D(QQuickWebView);
1888     forceActiveFocus();
1889     d->handleMouseEvent(event);
1890 }
1891
1892 void QQuickWebView::wheelEvent(QWheelEvent* event)
1893 {
1894     Q_D(QQuickWebView);
1895     d->pageView->eventHandler()->handleWheelEvent(event);
1896 }
1897
1898 void QQuickWebView::hoverEnterEvent(QHoverEvent* event)
1899 {
1900     Q_D(QQuickWebView);
1901     // Map HoverEnter to Move, for WebKit the distinction doesn't matter.
1902     d->pageView->eventHandler()->handleHoverMoveEvent(event);
1903 }
1904
1905 void QQuickWebView::hoverMoveEvent(QHoverEvent* event)
1906 {
1907     Q_D(QQuickWebView);
1908     d->pageView->eventHandler()->handleHoverMoveEvent(event);
1909 }
1910
1911 void QQuickWebView::hoverLeaveEvent(QHoverEvent* event)
1912 {
1913     Q_D(QQuickWebView);
1914     d->pageView->eventHandler()->handleHoverLeaveEvent(event);
1915 }
1916
1917 void QQuickWebView::dragMoveEvent(QDragMoveEvent* event)
1918 {
1919     Q_D(QQuickWebView);
1920     d->pageView->eventHandler()->handleDragMoveEvent(event);
1921 }
1922
1923 void QQuickWebView::dragEnterEvent(QDragEnterEvent* event)
1924 {
1925     Q_D(QQuickWebView);
1926     d->pageView->eventHandler()->handleDragEnterEvent(event);
1927 }
1928
1929 void QQuickWebView::dragLeaveEvent(QDragLeaveEvent* event)
1930 {
1931     Q_D(QQuickWebView);
1932     d->pageView->eventHandler()->handleDragLeaveEvent(event);
1933 }
1934
1935 void QQuickWebView::dropEvent(QDropEvent* event)
1936 {
1937     Q_D(QQuickWebView);
1938     d->pageView->eventHandler()->handleDropEvent(event);
1939 }
1940
1941 bool QQuickWebView::event(QEvent* ev)
1942 {
1943     // Re-implemented for possible future use without breaking binary compatibility.
1944     return QQuickFlickable::event(ev);
1945 }
1946
1947 WKPageRef QQuickWebView::pageRef() const
1948 {
1949     Q_D(const QQuickWebView);
1950     return toAPI(d->webPageProxy.get());
1951 }
1952
1953 QPointF QQuickWebView::contentPos() const
1954 {
1955     Q_D(const QQuickWebView);
1956     return d->contentPos();
1957 }
1958
1959 void QQuickWebView::setContentPos(const QPointF& pos)
1960 {
1961     Q_D(QQuickWebView);
1962
1963     if (pos == contentPos())
1964         return;
1965
1966     d->setContentPos(pos);
1967 }
1968
1969 void QQuickWebView::handleFlickableMousePress(const QPointF& position, qint64 eventTimestampMillis)
1970 {
1971     Q_D(QQuickWebView);
1972     d->axisLocker.setReferencePosition(position);
1973     QMouseEvent mouseEvent(QEvent::MouseButtonPress, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1974     mouseEvent.setTimestamp(eventTimestampMillis);
1975     QQuickFlickable::mousePressEvent(&mouseEvent);
1976 }
1977
1978 void QQuickWebView::handleFlickableMouseMove(const QPointF& position, qint64 eventTimestampMillis)
1979 {
1980     Q_D(QQuickWebView);
1981     QMouseEvent mouseEvent(QEvent::MouseMove, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1982     mouseEvent.setTimestamp(eventTimestampMillis);
1983     QQuickFlickable::mouseMoveEvent(&mouseEvent);
1984 }
1985
1986 void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 eventTimestampMillis)
1987 {
1988     Q_D(QQuickWebView);
1989     QMouseEvent mouseEvent(QEvent::MouseButtonRelease, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1990     d->axisLocker.reset();
1991     mouseEvent.setTimestamp(eventTimestampMillis);
1992     QQuickFlickable::mouseReleaseEvent(&mouseEvent);
1993 }
1994
1995 /*!
1996     \qmlmethod void WebView::loadHtml(string html, url baseUrl, url unreachableUrl)
1997     \brief Loads the specified \a html as the content of the web view.
1998
1999     (This method offers a lower-level alternative to the \c{url} property,
2000     which references HTML pages via URL.)
2001
2002     External objects such as stylesheets or images referenced in the HTML
2003     document are located relative to \a baseUrl. For example if provided \a html
2004     was originally retrieved from \c http://www.example.com/documents/overview.html
2005     and that was the base url, then an image referenced with the relative url \c diagram.png
2006     would be looked for at \c{http://www.example.com/documents/diagram.png}.
2007
2008     If an \a unreachableUrl is passed it is used as the url for the loaded
2009     content. This is typically used to display error pages for a failed
2010     load.
2011
2012     \sa WebView::url
2013 */
2014 void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl, const QUrl& unreachableUrl)
2015 {
2016     Q_D(QQuickWebView);
2017     if (unreachableUrl.isValid())
2018         d->webPageProxy->loadAlternateHTMLString(html, baseUrl.toString(), unreachableUrl.toString());
2019     else
2020         d->webPageProxy->loadHTMLString(html, baseUrl.toString());
2021 }
2022
2023 qreal QQuickWebView::zoomFactor() const
2024 {
2025     Q_D(const QQuickWebView);
2026     return d->zoomFactor();
2027 }
2028
2029 void QQuickWebView::setZoomFactor(qreal factor)
2030 {
2031
2032     Q_D(QQuickWebView);
2033     d->setZoomFactor(factor);
2034 }
2035
2036 void QQuickWebView::runJavaScriptInMainFrame(const QString &script, QObject *receiver, const char *method)
2037 {
2038     Q_D(QQuickWebView);
2039
2040     JSCallbackClosure* closure = new JSCallbackClosure;
2041     closure->receiver = receiver;
2042     closure->method = method;
2043
2044     d->webPageProxy.get()->runJavaScriptInMainFrame(script, ScriptValueCallback::create(closure, javaScriptCallback));
2045 }
2046
2047 bool QQuickWebView::allowAnyHTTPSCertificateForLocalHost() const
2048 {
2049     Q_D(const QQuickWebView);
2050     return d->m_allowAnyHTTPSCertificateForLocalHost;
2051 }
2052
2053 void QQuickWebView::setAllowAnyHTTPSCertificateForLocalHost(bool allow)
2054 {
2055     Q_D(QQuickWebView);
2056     d->m_allowAnyHTTPSCertificateForLocalHost = allow;
2057 }
2058
2059 /*!
2060     \qmlsignal WebView::onLoadingChanged(loadRequest)
2061
2062     Occurs when any page load begins, ends, or fails. Various read-only
2063     parameters are available on the \a loadRequest:
2064
2065     \list
2066
2067     \li \c{url}: the location of the resource that is loading.
2068
2069     \li \c{status}: Reflects one of three load states:
2070        \c{LoadStartedStatus}, \c{LoadSucceededStatus}, or
2071        \c{LoadFailedStatus}. See \c{WebView::LoadStatus}.
2072
2073     \li \c{errorString}: description of load error.
2074
2075     \li \c{errorCode}: HTTP error code.
2076
2077     \li \c{errorDomain}: high-level error types, one of
2078     \c{NetworkErrorDomain}, \c{HttpErrorDomain}, \c{InternalErrorDomain},
2079     \c{DownloadErrorDomain}, or \c{NoErrorDomain}.  See
2080     \l{WebView::ErrorDomain}.
2081
2082     \endlist
2083
2084     \sa WebView::loading
2085 */
2086
2087 /*!
2088     \qmlsignal WebView::onLinkHovered(hoveredUrl, hoveredTitle)
2089
2090     Within a mouse-driven interface, this signal is emitted when a mouse
2091     pointer passes over a link, corresponding to the \c{mouseover} DOM
2092     event.  (May also occur in touch interfaces for \c{mouseover} events
2093     that are not cancelled with \c{preventDefault()}.)  The \a{hoveredUrl}
2094     provides the link's location, and the \a{hoveredTitle} is any avalable
2095     link text.
2096 */
2097
2098 /*!
2099     \qmlsignal WebView::onNavigationRequested(request)
2100
2101     Occurs for various kinds of navigation.  If the application listens
2102     for this signal, it must set the \c{request.action} to either of the
2103     following \l{WebView::NavigationRequestAction} enum values:
2104
2105     \list
2106
2107     \li \c{AcceptRequest}: Allow navigation to external pages within the
2108     web view. This represents the default behavior when no listener is
2109     active.
2110
2111     \li \c{IgnoreRequest}: Suppress navigation to new pages within the web
2112     view.  (The listener may then delegate navigation externally to
2113     the browser application.)
2114
2115     \endlist
2116
2117     The \a{request} also provides the following read-only values:
2118
2119     \list
2120
2121     \li \c{url}: The location of the requested page.
2122
2123     \li \c{navigationType}: contextual information, one of
2124     \c{LinkClickedNavigation}, \c{BackForwardNavigation},
2125     \c{ReloadNavigation}, \c{FormSubmittedNavigation},
2126     \c{FormResubmittedNavigation}, or \c{OtherNavigation} enum values.
2127     See \l{WebView::NavigationType}.
2128
2129     \li \c{keyboardModifiers}: potential states for \l{Qt::KeyboardModifier}.
2130
2131     \li \c{mouseButton}: potential states for \l{Qt::MouseButton}.
2132
2133     \endlist
2134 */
2135
2136 /*!
2137     \qmlproperty enumeration WebView::ErrorDomain
2138
2139     Details various high-level error types.
2140
2141     \table
2142
2143     \header
2144     \li Constant
2145     \li Description
2146
2147     \row
2148     \li InternalErrorDomain
2149     \li Content fails to be interpreted by QtWebKit.
2150
2151     \row
2152     \li NetworkErrorDomain
2153     \li Error results from faulty network connection.
2154
2155     \row
2156     \li HttpErrorDomain
2157     \li Error is produced by server.
2158
2159     \row
2160     \li DownloadErrorDomain
2161     \li Error in saving file.
2162
2163     \row
2164     \li NoErrorDomain
2165     \li Unspecified fallback error.
2166
2167     \endtable
2168 */
2169
2170 /*!
2171     \qmlproperty enumeration WebView::NavigationType
2172
2173     Distinguishes context for various navigation actions.
2174
2175     \table
2176
2177     \header
2178     \li Constant
2179     \li Description
2180
2181     \row
2182     \li LinkClickedNavigation
2183     \li Navigation via link.
2184
2185     \row
2186     \li FormSubmittedNavigation
2187     \li Form data is posted.
2188
2189     \row
2190     \li BackForwardNavigation
2191     \li Navigation back and forth within session history.
2192
2193     \row
2194     \li ReloadNavigation
2195     \li The current page is reloaded.
2196
2197     \row
2198     \li FormResubmittedNavigation
2199     \li Form data is re-posted.
2200
2201     \row
2202     \li OtherNavigation
2203     \li Unspecified fallback method of navigation.
2204
2205     \endtable
2206 */
2207
2208 /*!
2209     \qmlproperty enumeration WebView::LoadStatus
2210
2211     Reflects a page's load status.
2212
2213     \table
2214
2215     \header
2216     \li Constant
2217     \li Description
2218
2219     \row
2220     \li LoadStartedStatus
2221     \li Page is currently loading.
2222
2223     \row
2224     \li LoadSucceededStatus
2225     \li Page has successfully loaded, and is not currently loading.
2226
2227     \row
2228     \li LoadFailedStatus
2229     \li Page has failed to load, and is not currently loading.
2230
2231     \endtable
2232 */
2233
2234 /*!
2235     \qmlproperty enumeration WebView::NavigationRequestAction
2236
2237     Specifies a policy when navigating a link to an external page.
2238
2239     \table
2240
2241     \header
2242     \li Constant
2243     \li Description
2244
2245     \row
2246     \li AcceptRequest
2247     \li Allow navigation to external pages within the web view.
2248
2249     \row
2250     \li IgnoreRequest
2251     \li Suppress navigation to new pages within the web view.
2252
2253     \endtable
2254 */
2255
2256 #include "moc_qquickwebview_p.cpp"