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