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