#include "config.h"
#include "qquickwebview_p.h"
#include "CoordinatedLayerTreeHostProxy.h"
#include "DownloadProxy.h"
#include "DrawingAreaProxyImpl.h"
#include "PageViewportControllerClientQt.h"
#include "QtDialogRunner.h"
#include "QtDownloadManager.h"
#include "QtWebContext.h"
#include "QtWebError.h"
#include "QtWebIconDatabaseClient.h"
#include "QtWebPageEventHandler.h"
#include "QtWebPagePolicyClient.h"
#include "WebBackForwardList.h"
#include "WebContext.h"
#include "WebFindOptions.h"
#if ENABLE(INSPECTOR_SERVER)
#include "WebInspectorProxy.h"
#include "WebInspectorServer.h"
#endif
#if ENABLE(FULLSCREEN_API)
#include "WebFullScreenManagerProxy.h"
#endif
#include "WebPageGroup.h"
#include "WebPreferences.h"
#include "qglobal.h"
#include "qquicknetworkreply_p.h"
#include "qquicknetworkrequest_p.h"
#include "qquickwebpage_p_p.h"
#include "qquickwebview_p_p.h"
#include "qwebdownloaditem_p_p.h"
#include "qwebiconimageprovider_p.h"
#include "qwebkittest_p.h"
#include "qwebloadrequest_p.h"
#include "qwebnavigationhistory_p.h"
#include "qwebnavigationhistory_p_p.h"
#include "qwebpreferences_p.h"
#include "qwebpreferences_p_p.h"
#include <JavaScriptCore/InitializeThreading.h>
#include <JavaScriptCore/JSBase.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <QDateTime>
#include <QMap>
#include <QtCore/QFile>
#include <QtQml/QJSValue>
#include <QtQuick/QQuickView>
#include <WKNumber.h>
#include <WKOpenPanelResultListener.h>
#include <WKPageGroup.h>
#include <WKPreferences.h>
#include <WKSerializedScriptValue.h>
#include <WKString.h>
#include <WKStringQt.h>
#include <WKURLQt.h>
#include <WebCore/CoordinatedGraphicsScene.h>
#include <WebCore/IntPoint.h>
#include <WebCore/IntRect.h>
#include <limits>
#include <wtf/Assertions.h>
#include <wtf/MainThread.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
using namespace WebCore;
using namespace WebKit;
static bool s_flickableViewportEnabled = true;
static const int kAxisLockSampleCount = 5;
static const qreal kAxisLockVelocityThreshold = 300;
static const qreal kAxisLockVelocityDirectionThreshold = 50;
typedef QMap<WKPageRef, QQuickWebViewPrivate*> PageToViewMap;
Q_GLOBAL_STATIC(PageToViewMap, pageToView)
static inline QQuickWebViewPrivate* toQQuickWebViewPrivate(const void* clientInfo)
{
ASSERT(clientInfo);
return reinterpret_cast<QQuickWebViewPrivate*>(const_cast<void*>(clientInfo));
}
struct JSCallbackClosure {
QPointer<QObject> receiver;
QByteArray method;
QJSValue value;
};
static inline QString toQString(JSStringRef string)
{
return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(string)), JSStringGetLength(string));
}
static inline QJSValue toQJSValue(JSStringRef string)
{
return QJSValue(toQString(string));
}
static QJSValue buildQJSValue(QJSEngine* engine, JSGlobalContextRef context, JSValueRef value, int depth)
{
QJSValue var;
JSValueRef exception = 0;
if (depth > 10)
return var;
switch (JSValueGetType(context, value)) {
case kJSTypeBoolean:
var = QJSValue(JSValueToBoolean(context, value));
break;
case kJSTypeNumber:
{
double number = JSValueToNumber(context, value, &exception);
if (!exception)
var = QJSValue(number);
}
break;
case kJSTypeString:
{
JSRetainPtr<JSStringRef> string = JSValueToStringCopy(context, value, &exception);
if (!exception)
var = toQJSValue(string.get());
}
break;
case kJSTypeObject:
{
JSObjectRef obj = JSValueToObject(context, value, &exception);
JSPropertyNameArrayRef names = JSObjectCopyPropertyNames(context, obj);
size_t length = JSPropertyNameArrayGetCount(names);
var = engine->newObject();
for (size_t i = 0; i < length; ++i) {
JSRetainPtr<JSStringRef> name = JSPropertyNameArrayGetNameAtIndex(names, i);
JSValueRef property = JSObjectGetProperty(context, obj, name.get(), &exception);
if (!exception) {
QJSValue value = buildQJSValue(engine, context, property, depth + 1);
var.setProperty(toQString(name.get()), value);
}
}
}
break;
}
return var;
}
static void javaScriptCallback(WKSerializedScriptValueRef valueRef, WKErrorRef, void* data)
{
JSCallbackClosure* closure = reinterpret_cast<JSCallbackClosure*>(data);
if (closure->method.size())
QMetaObject::invokeMethod(closure->receiver, closure->method);
else {
QJSValue function = closure->value;
if (function.isCallable()) {
QJSValue var;
if (valueRef) {
JSGlobalContextRef context = JSGlobalContextCreate(0);
JSValueRef exception = 0;
JSValueRef value = WKSerializedScriptValueDeserialize(valueRef, context, &exception);
var = buildQJSValue(function.engine(), context, value, 0);
JSGlobalContextRelease(context);
}
QList<QJSValue> args;
args.append(var);
function.call(args);
}
}
delete closure;
}
static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject)
{
if (s_flickableViewportEnabled)
return new QQuickWebViewFlickablePrivate(publicObject);
return new QQuickWebViewLegacyPrivate(publicObject);
}
QQuickWebViewPrivate* QQuickWebViewPrivate::get(WKPageRef page)
{
return pageToView()->value(page);
}
QQuickWebViewPrivate::FlickableAxisLocker::FlickableAxisLocker()
: m_allowedDirection(QQuickFlickable::AutoFlickDirection)
, m_time(0), m_sampleCount(0)
{
}
QVector2D QQuickWebViewPrivate::FlickableAxisLocker::touchVelocity(const QTouchEvent* event)
{
static bool touchVelocityAvailable = event->device()->capabilities().testFlag(QTouchDevice::Velocity);
const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
if (touchVelocityAvailable)
return touchPoint.velocity();
const QLineF movementLine(touchPoint.pos(), m_initialPosition);
const ulong elapsed = event->timestamp() - m_time;
if (!elapsed)
return QVector2D(0, 0);
return QVector2D(1000 * movementLine.dx() / elapsed, 1000 * movementLine.dy() / elapsed);
}
void QQuickWebViewPrivate::FlickableAxisLocker::update(const QTouchEvent* event)
{
ASSERT(event->touchPoints().size() == 1);
const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
++m_sampleCount;
if (m_sampleCount == 1) {
m_initialPosition = touchPoint.pos();
m_time = event->timestamp();
return;
}
if (m_sampleCount > kAxisLockSampleCount
|| m_allowedDirection == QQuickFlickable::HorizontalFlick
|| m_allowedDirection == QQuickFlickable::VerticalFlick)
return;
QVector2D velocity = touchVelocity(event);
qreal directionIndicator = qAbs(velocity.x()) - qAbs(velocity.y());
if (velocity.length() > kAxisLockVelocityThreshold && qAbs(directionIndicator) > kAxisLockVelocityDirectionThreshold)
m_allowedDirection = (directionIndicator > 0) ? QQuickFlickable::HorizontalFlick : QQuickFlickable::VerticalFlick;
}
void QQuickWebViewPrivate::FlickableAxisLocker::setReferencePosition(const QPointF& position)
{
m_lockReferencePosition = position;
}
void QQuickWebViewPrivate::FlickableAxisLocker::reset()
{
m_allowedDirection = QQuickFlickable::AutoFlickDirection;
m_sampleCount = 0;
}
QPointF QQuickWebViewPrivate::FlickableAxisLocker::adjust(const QPointF& position)
{
if (m_allowedDirection == QQuickFlickable::HorizontalFlick)
return QPointF(position.x(), m_lockReferencePosition.y());
if (m_allowedDirection == QQuickFlickable::VerticalFlick)
return QPointF(m_lockReferencePosition.x(), position.y());
return position;
}
QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
: q_ptr(viewport)
, experimental(new QQuickWebViewExperimental(viewport, this))
, context(0)
, alertDialog(0)
, confirmDialog(0)
, promptDialog(0)
, authenticationDialog(0)
, certificateVerificationDialog(0)
, itemSelector(0)
, proxyAuthenticationDialog(0)
, filePicker(0)
, databaseQuotaDialog(0)
, colorChooser(0)
, m_betweenLoadCommitAndFirstFrame(false)
, m_useDefaultContentItemSize(true)
, m_navigatorQtObjectEnabled(false)
, m_renderToOffscreenBuffer(false)
, m_allowAnyHTTPSCertificateForLocalHost(false)
, m_loadProgress(0)
{
viewport->setClip(true);
viewport->setPixelAligned(true);
QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged()));
QObject::connect(viewport, SIGNAL(urlChanged()), viewport, SLOT(_q_onUrlChanged()));
pageView.reset(new QQuickWebPage(viewport));
}
QQuickWebViewPrivate::~QQuickWebViewPrivate()
{
webPageProxy->close();
pageToView()->remove(webPage.get());
}
void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
pageGroup = pageGroupRef;
if (!pageGroup)
pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(0));
context = contextRef ? QtWebContext::create(contextRef) : QtWebContext::defaultContext();
webPageProxy = toImpl(context->context())->createWebPage(&pageClient, toImpl(pageGroup.get()));
webPage = toAPI(webPageProxy.get());
pageToView()->insert(webPage.get(), this);
webPageProxy->setUseFixedLayout(s_flickableViewportEnabled);
#if ENABLE(FULLSCREEN_API)
webPageProxy->fullScreenManager()->setWebView(q_ptr);
#endif
pageEventHandler.reset(new QtWebPageEventHandler(webPage.get(), pageView.data(), q_ptr));
{
WKPageFindClient findClient;
memset(&findClient, 0, sizeof(WKPageFindClient));
findClient.version = kWKPageFindClientCurrentVersion;
findClient.clientInfo = this;
findClient.didFindString = didFindString;
findClient.didFailToFindString = didFailToFindString;
WKPageSetPageFindClient(webPage.get(), &findClient);
}
{
WKPageLoaderClient loadClient;
memset(&loadClient, 0, sizeof(WKPageLoaderClient));
loadClient.version = kWKPageLoaderClientCurrentVersion;
loadClient.clientInfo = this;
loadClient.didStartProvisionalLoadForFrame = didStartProvisionalLoadForFrame;
loadClient.didReceiveServerRedirectForProvisionalLoadForFrame = didReceiveServerRedirectForProvisionalLoadForFrame;
loadClient.didFailProvisionalLoadWithErrorForFrame = didFailLoad;
loadClient.didCommitLoadForFrame = didCommitLoadForFrame;
loadClient.didFinishLoadForFrame = didFinishLoadForFrame;
loadClient.didFailLoadWithErrorForFrame = didFailLoad;
loadClient.didSameDocumentNavigationForFrame = didSameDocumentNavigationForFrame;
loadClient.didReceiveTitleForFrame = didReceiveTitleForFrame;
loadClient.didStartProgress = didStartProgress;
loadClient.didChangeProgress = didChangeProgress;
loadClient.didFinishProgress = didFinishProgress;
loadClient.didChangeBackForwardList = didChangeBackForwardList;
WKPageSetPageLoaderClient(webPage.get(), &loadClient);
}
pagePolicyClient.reset(new QtWebPagePolicyClient(webPage.get(), q_ptr));
pageUIClient.reset(new QtWebPageUIClient(webPage.get(), q_ptr));
navigationHistory = adoptPtr(QWebNavigationHistoryPrivate::createHistory(webPage.get()));
QtWebIconDatabaseClient* iconDatabase = context->iconDatabase();
QObject::connect(iconDatabase, SIGNAL(iconChangedForPageURL(QString)), q_ptr, SLOT(_q_onIconChangedForPageURL(QString)));
WKPreferencesRef preferencesRef = WKPageGroupGetPreferences(pageGroup.get());
WKPreferencesSetAcceleratedCompositingEnabled(preferencesRef, true);
bool showDebugVisuals = qgetenv("WEBKIT_SHOW_COMPOSITING_DEBUG_VISUALS") == "1";
WKPreferencesSetCompositingBordersVisible(preferencesRef, showDebugVisuals);
WKPreferencesSetCompositingRepaintCountersVisible(preferencesRef, showDebugVisuals);
WKPreferencesSetFrameFlatteningEnabled(preferencesRef, true);
WKPreferencesSetWebGLEnabled(preferencesRef, true);
webPageProxy->pageGroup()->preferences()->setForceCompositingMode(true);
pageClient.initialize(q_ptr, pageEventHandler.data(), &undoController);
webPageProxy->initializeWebPage();
webPageProxy->registerApplicationScheme(ASCIILiteral("qrc"));
q_ptr->setAcceptedMouseButtons(Qt::MouseButtonMask);
q_ptr->setAcceptHoverEvents(true);
q_ptr->setFlag(QQuickItem::ItemAcceptsDrops, true);
}
void QQuickWebViewPrivate::didStartProvisionalLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
WKRetainPtr<WKURLRef> url = adoptWK(WKFrameCopyProvisionalURL(frame));
QQuickWebView* const q = toQQuickWebViewPrivate(clientInfo)->q_func();
q->emitUrlChangeIfNeeded();
QWebLoadRequest loadRequest(WKURLCopyQUrl(url.get()), QQuickWebView::LoadStartedStatus);
emit q->loadingChanged(&loadRequest);
}
void QQuickWebViewPrivate::didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
toQQuickWebViewPrivate(clientInfo)->q_func()->emitUrlChangeIfNeeded();
}
void QQuickWebViewPrivate::didFailLoad(WKPageRef, WKFrameRef frame, WKErrorRef errorRef, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
QQuickWebView* const q = toQQuickWebViewPrivate(clientInfo)->q_func();
ASSERT(!q->loading());
QtWebError error(errorRef);
if (error.isCancellation()) {
QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadStoppedStatus);
emit q->loadingChanged(&loadRequest);
return;
}
int errorCode = error.errorCode();
if (errorCode == kWKErrorCodeFrameLoadInterruptedByPolicyChange && errorCode == kWKErrorCodePlugInWillHandleLoad) {
QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadSucceededStatus);
q->emitUrlChangeIfNeeded();
emit q->loadingChanged(&loadRequest);
return;
}
toImpl(frame)->setUnreachableURL(error.url());
q->emitUrlChangeIfNeeded();
QWebLoadRequest loadRequest(error.url(), QQuickWebView::LoadFailedStatus, error.description(), static_cast<QQuickWebView::ErrorDomain>(error.type()), errorCode);
emit q->loadingChanged(&loadRequest);
}
void QQuickWebViewPrivate::didCommitLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
QQuickWebViewPrivate* d = toQQuickWebViewPrivate(clientInfo);
PageViewportController* pageViewportController = d->viewportController();
if (pageViewportController)
pageViewportController->didCommitLoad();
QQuickWebView* const q = d->q_func();
ASSERT(q->loading());
d->m_betweenLoadCommitAndFirstFrame = true;
emit q->navigationHistoryChanged();
emit q->titleChanged();
}
void QQuickWebViewPrivate::didFinishLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
QQuickWebView* const q = toQQuickWebViewPrivate(clientInfo)->q_func();
ASSERT(!q->loading());
QWebLoadRequest loadRequest(q->url(), QQuickWebView::LoadSucceededStatus);
emit q->loadingChanged(&loadRequest);
}
void QQuickWebViewPrivate::didSameDocumentNavigationForFrame(WKPageRef, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
QQuickWebView* const q = toQQuickWebViewPrivate(clientInfo)->q_func();
q->emitUrlChangeIfNeeded();
emit q->navigationHistoryChanged();
}
void QQuickWebViewPrivate::didReceiveTitleForFrame(WKPageRef, WKStringRef title, WKFrameRef frame, WKTypeRef, const void* clientInfo)
{
if (!WKFrameIsMainFrame(frame))
return;
emit toQQuickWebViewPrivate(clientInfo)->q_func()->titleChanged();
}
void QQuickWebViewPrivate::didStartProgress(WKPageRef, const void* clientInfo)
{
toQQuickWebViewPrivate(clientInfo)->loadProgressDidChange(0);
}
void QQuickWebViewPrivate::didChangeProgress(WKPageRef page, const void* clientInfo)
{
toQQuickWebViewPrivate(clientInfo)->loadProgressDidChange(WKPageGetEstimatedProgress(page) * 100);
}
void QQuickWebViewPrivate::didFinishProgress(WKPageRef, const void* clientInfo)
{
toQQuickWebViewPrivate(clientInfo)->loadProgressDidChange(100);
}
void QQuickWebViewPrivate::didChangeBackForwardList(WKPageRef, WKBackForwardListItemRef, WKArrayRef, const void *clientInfo)
{
toQQuickWebViewPrivate(clientInfo)->navigationHistory->d->reset();
}
void QQuickWebViewPrivate::setTransparentBackground(bool enable)
{
webPageProxy->setDrawsTransparentBackground(enable);
}
bool QQuickWebViewPrivate::transparentBackground() const
{
return webPageProxy->drawsTransparentBackground();
}
void QQuickWebViewPrivate::loadProgressDidChange(int loadProgress)
{
Q_Q(QQuickWebView);
m_loadProgress = loadProgress;
emit q->loadProgressChanged();
}
void QQuickWebViewPrivate::handleMouseEvent(QMouseEvent* event)
{
switch (event->type()) {
case QEvent::MouseButtonPress:
pageEventHandler->handleMousePressEvent(event);
break;
case QEvent::MouseMove:
pageEventHandler->handleMouseMoveEvent(event);
break;
case QEvent::MouseButtonRelease:
pageEventHandler->handleMouseReleaseEvent(event);
break;
case QEvent::MouseButtonDblClick:
event->accept();
break;
default:
ASSERT_NOT_REACHED();
break;
}
}
void QQuickWebViewPrivate::setNeedsDisplay()
{
Q_Q(QQuickWebView);
if (renderToOffscreenBuffer()) {
QImage dummyImage(1, 1, QImage::Format_ARGB32);
QPainter painter(&dummyImage);
q->page()->d->paint(&painter);
return;
}
q->page()->update();
}
void QQuickWebViewPrivate::didRenderFrame()
{
Q_Q(QQuickWebView);
if (m_betweenLoadCommitAndFirstFrame) {
emit q->experimental()->loadVisuallyCommitted();
m_betweenLoadCommitAndFirstFrame = false;
}
}
void QQuickWebViewPrivate::processDidCrash()
{
Q_Q(QQuickWebView);
QUrl url(KURL(WebCore::ParsedURLString, webPageProxy->urlAtProcessExit()));
qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(url.toString(QUrl::RemoveUserInfo)));
pageEventHandler->resetGestureRecognizers();
if (m_loadProgress > 0 && m_loadProgress < 100) {
QWebLoadRequest loadRequest(url, QQuickWebView::LoadFailedStatus, QLatin1String("The web process crashed."), QQuickWebView::InternalErrorDomain, 0);
loadProgressDidChange(100);
emit q->loadingChanged(&loadRequest);
}
}
void QQuickWebViewPrivate::didRelaunchProcess()
{
qWarning("WARNING: The web process has been successfully restarted.");
if (DrawingAreaProxy *drawingArea = webPageProxy->drawingArea()) {
drawingArea->setSize(viewSize(), IntSize(), IntSize());
updateViewportSize();
updateUserScripts();
updateSchemeDelegates();
}
}
PassOwnPtr<DrawingAreaProxy> QQuickWebViewPrivate::createDrawingAreaProxy()
{
return DrawingAreaProxyImpl::create(webPageProxy.get());
}
void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download)
{
Q_Q(QQuickWebView);
QWebDownloadItem* downloadItem = new QWebDownloadItem();
downloadItem->d->downloadProxy = download;
q->connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), q, SLOT(_q_onReceivedResponseFromDownload(QWebDownloadItem*)));
QtWebContext::defaultContext()->downloadManager()->addDownload(toAPI(download), downloadItem);
}
void QQuickWebViewPrivate::_q_onVisibleChanged()
{
webPageProxy->viewStateDidChange(WebPageProxy::ViewIsVisible);
}
void QQuickWebViewPrivate::_q_onUrlChanged()
{
updateIcon();
}
void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QString& pageUrl)
{
if (pageUrl != m_currentUrl)
return;
updateIcon();
}
void QQuickWebViewPrivate::updateIcon()
{
Q_Q(QQuickWebView);
QQuickView* view = qobject_cast<QQuickView*>(q->window());
if (!view)
return;
QWebIconImageProvider* provider = static_cast<QWebIconImageProvider*>(
view->engine()->imageProvider(QWebIconImageProvider::identifier()));
if (!provider)
return;
QUrl iconUrl = provider->iconURLForPageURLInContext(m_currentUrl, context);
if (iconUrl == m_iconUrl)
return;
m_iconUrl = iconUrl;
emit q->iconChanged();
}
void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* downloadItem)
{
if (!downloadItem)
return;
Q_Q(QQuickWebView);
QQmlEngine::setObjectOwnership(downloadItem, QQmlEngine::JavaScriptOwnership);
emit q->experimental()->downloadRequested(downloadItem);
}
void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForAlert(alertText))
return;
dialogRunner.run();
}
bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForConfirm(message))
return true;
dialogRunner.run();
return dialogRunner.wasAccepted();
}
QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForPrompt(message, defaultValue)) {
ok = true;
return defaultValue;
}
dialogRunner.run();
ok = dialogRunner.wasAccepted();
return dialogRunner.result();
}
void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForAuthentication(hostname, realm, prefilledUsername))
return;
dialogRunner.run();
username = dialogRunner.username();
password = dialogRunner.password();
}
void QQuickWebViewPrivate::handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForProxyAuthentication(hostname, port, prefilledUsername))
return;
dialogRunner.run();
username = dialogRunner.username();
password = dialogRunner.password();
}
bool QQuickWebViewPrivate::handleCertificateVerificationRequest(const QString& hostname)
{
Q_Q(QQuickWebView);
if (m_allowAnyHTTPSCertificateForLocalHost
&& (hostname == QStringLiteral("127.0.0.1") || hostname == QStringLiteral("localhost")))
return true;
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForCertificateVerification(hostname))
return false;
dialogRunner.run();
return dialogRunner.wasAccepted();
}
void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForFilePicker(selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection)))
return;
dialogRunner.run();
if (dialogRunner.wasAccepted()) {
QStringList selectedPaths = dialogRunner.filePaths();
Vector<RefPtr<APIObject> > wkFiles(selectedPaths.size());
for (unsigned i = 0; i < selectedPaths.size(); ++i)
wkFiles[i] = WebURL::create(QUrl::fromLocalFile(selectedPaths.at(i)).toString());
WKOpenPanelResultListenerChooseFiles(listenerRef, toAPI(ImmutableArray::adopt(wkFiles).leakRef()));
} else
WKOpenPanelResultListenerCancel(listenerRef);
}
quint64 QQuickWebViewPrivate::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage)
{
Q_Q(QQuickWebView);
QtDialogRunner dialogRunner(q);
if (!dialogRunner.initForDatabaseQuotaDialog(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage))
return 0;
dialogRunner.run();
return dialogRunner.wasAccepted() ? dialogRunner.databaseQuota() : 0;
}
QQuickWebViewAttached::QQuickWebViewAttached(QObject* object)
: QObject(object)
, m_view(0)
{
}
void QQuickWebViewAttached::setView(QQuickWebView* view)
{
if (m_view == view)
return;
m_view = view;
emit viewChanged();
}
QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object)
{
return new QQuickWebViewAttached(object);
}
void QQuickWebViewPrivate::addAttachedPropertyTo(QObject* object)
{
Q_Q(QQuickWebView);
QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object));
attached->setView(q);
}
bool QQuickWebViewPrivate::navigatorQtObjectEnabled() const
{
return m_navigatorQtObjectEnabled;
}
void QQuickWebViewPrivate::setNavigatorQtObjectEnabled(bool enabled)
{
ASSERT(enabled != m_navigatorQtObjectEnabled);
m_navigatorQtObjectEnabled = enabled;
static WKStringRef messageName = WKStringCreateWithUTF8CString("SetNavigatorQtObjectEnabled");
WKRetainPtr<WKBooleanRef> wkEnabled = adoptWK(WKBooleanCreate(enabled));
WKPagePostMessageToInjectedBundle(webPage.get(), messageName, wkEnabled.get());
}
static WKRetainPtr<WKStringRef> readUserScript(const QUrl& url)
{
QString path;
if (url.isLocalFile())
path = url.toLocalFile();
else if (url.scheme() == QLatin1String("qrc"))
path = QStringLiteral(":") + url.path();
else {
qWarning("QQuickWebView: Couldn't open '%s' as user script because only file:/// and qrc:/// URLs are supported.", qPrintable(url.toString()));
return 0;
}
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning("QQuickWebView: Couldn't open '%s' as user script due to error '%s'.", qPrintable(url.toString()), qPrintable(file.errorString()));
return 0;
}
QByteArray contents = file.readAll();
if (contents.isEmpty())
qWarning("QQuickWebView: Ignoring '%s' as user script because file is empty.", qPrintable(url.toString()));
return adoptWK(WKStringCreateWithUTF8CString(contents.constData()));
}
void QQuickWebViewPrivate::updateUserScripts()
{
WKPageGroupRemoveAllUserScripts(pageGroup.get());
for (unsigned i = 0; i < userScripts.size(); ++i) {
const QUrl& url = userScripts.at(i);
if (!url.isValid()) {
qWarning("QQuickWebView: Couldn't open '%s' as user script because URL is invalid.", qPrintable(url.toString()));
continue;
}
WKRetainPtr<WKStringRef> contents = readUserScript(url);
if (!contents || WKStringIsEmpty(contents.get()))
continue;
WKPageGroupAddUserScript(pageGroup.get(), contents.get(), 0, 0, 0, kWKInjectInTopFrameOnly, kWKInjectAtDocumentEnd);
}
}
void QQuickWebViewPrivate::updateSchemeDelegates()
{
webPageProxy->registerApplicationScheme(ASCIILiteral("qrc"));
QQmlListProperty<QQuickUrlSchemeDelegate> schemes = experimental->schemeDelegates();
for (int i = 0, numSchemes = experimental->schemeDelegates_Count(&schemes); i < numSchemes; ++i) {
QQuickUrlSchemeDelegate* scheme = experimental->schemeDelegates_At(&schemes, i);
webPageProxy->registerApplicationScheme(scheme->scheme());
}
}
QPointF QQuickWebViewPrivate::contentPos() const
{
Q_Q(const QQuickWebView);
return QPointF(q->contentX(), q->contentY());
}
void QQuickWebViewPrivate::setContentPos(const QPointF& pos)
{
Q_Q(QQuickWebView);
q->setContentX(pos.x());
q->setContentY(pos.y());
}
WebCore::IntSize QQuickWebViewPrivate::viewSize() const
{
return WebCore::IntSize(pageView->width(), pageView->height());
}
void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(WKStringRef message)
{
QVariantMap variantMap;
variantMap.insert(QLatin1String("data"), WKStringCopyQString(message));
variantMap.insert(QLatin1String("origin"), q_ptr->url());
emit q_ptr->experimental()->messageReceived(variantMap);
}
CoordinatedGraphicsScene* QQuickWebViewPrivate::coordinatedGraphicsScene()
{
if (webPageProxy && webPageProxy->drawingArea() && webPageProxy->drawingArea()->coordinatedLayerTreeHostProxy())
return webPageProxy->drawingArea()->coordinatedLayerTreeHostProxy()->coordinatedGraphicsScene();
return 0;
}
float QQuickWebViewPrivate::deviceScaleFactor()
{
return webPageProxy->deviceScaleFactor();
}
void QQuickWebViewPrivate::setIntrinsicDeviceScaleFactor(float scaleFactor)
{
webPageProxy->setIntrinsicDeviceScaleFactor(scaleFactor);
}
QQuickWebViewLegacyPrivate::QQuickWebViewLegacyPrivate(QQuickWebView* viewport)
: QQuickWebViewPrivate(viewport)
{
}
void QQuickWebViewLegacyPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
_q_onVisibleChanged();
}
void QQuickWebViewLegacyPrivate::updateViewportSize()
{
Q_Q(QQuickWebView);
QSizeF viewportSize = q->boundingRect().size();
if (viewportSize.isEmpty())
return;
pageView->setContentsSize(viewportSize);
if (DrawingAreaProxy *drawingArea = webPageProxy->drawingArea()) {
drawingArea->setSize(viewportSize.toSize(), IntSize(), IntSize());
drawingArea->setVisibleContentsRect(FloatRect(FloatPoint(), FloatSize(viewportSize)), FloatPoint());
}
}
qreal QQuickWebViewLegacyPrivate::zoomFactor() const
{
return WKPageGetPageZoomFactor(webPage.get());
}
void QQuickWebViewLegacyPrivate::setZoomFactor(qreal factor)
{
WKPageSetPageZoomFactor(webPage.get(), factor);
}
QQuickWebViewFlickablePrivate::QQuickWebViewFlickablePrivate(QQuickWebView* viewport)
: QQuickWebViewPrivate(viewport)
{
}
void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
QQuickWebViewPrivate::initialize(contextRef, pageGroupRef);
}
void QQuickWebViewFlickablePrivate::onComponentComplete()
{
QQuickWebViewPrivate::onComponentComplete();
Q_Q(QQuickWebView);
m_pageViewportControllerClient.reset(new PageViewportControllerClientQt(q, pageView.data()));
m_pageViewportController.reset(new PageViewportController(webPageProxy.get(), m_pageViewportControllerClient.data()));
pageEventHandler->setViewportController(m_pageViewportControllerClient.data());
_q_onVisibleChanged();
}
void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& newAttributes)
{
if (m_pageViewportController)
m_pageViewportController->didChangeViewportAttributes(newAttributes);
}
void QQuickWebViewFlickablePrivate::updateViewportSize()
{
Q_Q(QQuickWebView);
if (m_pageViewportController)
m_pageViewportController->didChangeViewportSize(FloatSize(q->width(), q->height()));
}
void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos)
{
if (m_pageViewportController)
m_pageViewportController->pageDidRequestScroll(pos);
}
QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView, QQuickWebViewPrivate* webViewPrivate)
: QObject(webView)
, q_ptr(webView)
, d_ptr(webViewPrivate)
, schemeParent(new QObject(this))
, m_test(new QWebKitTest(webViewPrivate, this))
{
}
QQuickWebViewExperimental::~QQuickWebViewExperimental()
{
}
void QQuickWebViewExperimental::setRenderToOffscreenBuffer(bool enable)
{
Q_D(QQuickWebView);
d->setRenderToOffscreenBuffer(enable);
}
bool QQuickWebViewExperimental::renderToOffscreenBuffer() const
{
Q_D(const QQuickWebView);
return d->renderToOffscreenBuffer();
}
bool QQuickWebViewExperimental::transparentBackground() const
{
Q_D(const QQuickWebView);
return d->transparentBackground();
}
void QQuickWebViewExperimental::setTransparentBackground(bool enable)
{
Q_D(QQuickWebView);
d->setTransparentBackground(enable);
}
bool QQuickWebViewExperimental::useDefaultContentItemSize() const
{
Q_D(const QQuickWebView);
return d->m_useDefaultContentItemSize;
}
void QQuickWebViewExperimental::setUseDefaultContentItemSize(bool enable)
{
Q_D(QQuickWebView);
d->m_useDefaultContentItemSize = enable;
}
int QQuickWebViewExperimental::preferredMinimumContentsWidth() const
{
Q_D(const QQuickWebView);
return d->webPageProxy->pageGroup()->preferences()->layoutFallbackWidth();
}
void QQuickWebViewExperimental::setPreferredMinimumContentsWidth(int width)
{
Q_D(QQuickWebView);
WebPreferences* webPreferences = d->webPageProxy->pageGroup()->preferences();
if (width == webPreferences->layoutFallbackWidth())
return;
webPreferences->setLayoutFallbackWidth(width);
emit preferredMinimumContentsWidthChanged();
}
void QQuickWebViewExperimental::setFlickableViewportEnabled(bool enable)
{
s_flickableViewportEnabled = enable;
}
bool QQuickWebViewExperimental::flickableViewportEnabled()
{
return s_flickableViewportEnabled;
}
void QQuickWebViewExperimental::postMessage(const QString& message)
{
Q_D(QQuickWebView);
static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageToNavigatorQtObject");
WKRetainPtr<WKStringRef> contents = adoptWK(WKStringCreateWithQString(message));
WKPagePostMessageToInjectedBundle(d->webPage.get(), messageName, contents.get());
}
QQmlComponent* QQuickWebViewExperimental::alertDialog() const
{
Q_D(const QQuickWebView);
return d->alertDialog;
}
void QQuickWebViewExperimental::setAlertDialog(QQmlComponent* alertDialog)
{
Q_D(QQuickWebView);
if (d->alertDialog == alertDialog)
return;
d->alertDialog = alertDialog;
emit alertDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::confirmDialog() const
{
Q_D(const QQuickWebView);
return d->confirmDialog;
}
void QQuickWebViewExperimental::setConfirmDialog(QQmlComponent* confirmDialog)
{
Q_D(QQuickWebView);
if (d->confirmDialog == confirmDialog)
return;
d->confirmDialog = confirmDialog;
emit confirmDialogChanged();
}
QWebNavigationHistory* QQuickWebViewExperimental::navigationHistory() const
{
return d_ptr->navigationHistory.get();
}
QQmlComponent* QQuickWebViewExperimental::promptDialog() const
{
Q_D(const QQuickWebView);
return d->promptDialog;
}
QWebPreferences* QQuickWebViewExperimental::preferences() const
{
QQuickWebViewPrivate* const d = d_ptr;
if (!d->preferences)
d->preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(d));
return d->preferences.get();
}
void QQuickWebViewExperimental::setPromptDialog(QQmlComponent* promptDialog)
{
Q_D(QQuickWebView);
if (d->promptDialog == promptDialog)
return;
d->promptDialog = promptDialog;
emit promptDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::authenticationDialog() const
{
Q_D(const QQuickWebView);
return d->authenticationDialog;
}
void QQuickWebViewExperimental::setAuthenticationDialog(QQmlComponent* authenticationDialog)
{
Q_D(QQuickWebView);
if (d->authenticationDialog == authenticationDialog)
return;
d->authenticationDialog = authenticationDialog;
emit authenticationDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::proxyAuthenticationDialog() const
{
Q_D(const QQuickWebView);
return d->proxyAuthenticationDialog;
}
void QQuickWebViewExperimental::setProxyAuthenticationDialog(QQmlComponent* proxyAuthenticationDialog)
{
Q_D(QQuickWebView);
if (d->proxyAuthenticationDialog == proxyAuthenticationDialog)
return;
d->proxyAuthenticationDialog = proxyAuthenticationDialog;
emit proxyAuthenticationDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::certificateVerificationDialog() const
{
Q_D(const QQuickWebView);
return d->certificateVerificationDialog;
}
void QQuickWebViewExperimental::setCertificateVerificationDialog(QQmlComponent* certificateVerificationDialog)
{
Q_D(QQuickWebView);
if (d->certificateVerificationDialog == certificateVerificationDialog)
return;
d->certificateVerificationDialog = certificateVerificationDialog;
emit certificateVerificationDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::itemSelector() const
{
Q_D(const QQuickWebView);
return d->itemSelector;
}
void QQuickWebViewExperimental::setItemSelector(QQmlComponent* itemSelector)
{
Q_D(QQuickWebView);
if (d->itemSelector == itemSelector)
return;
d->itemSelector = itemSelector;
emit itemSelectorChanged();
}
QQmlComponent* QQuickWebViewExperimental::filePicker() const
{
Q_D(const QQuickWebView);
return d->filePicker;
}
void QQuickWebViewExperimental::setFilePicker(QQmlComponent* filePicker)
{
Q_D(QQuickWebView);
if (d->filePicker == filePicker)
return;
d->filePicker = filePicker;
emit filePickerChanged();
}
QQmlComponent* QQuickWebViewExperimental::databaseQuotaDialog() const
{
Q_D(const QQuickWebView);
return d->databaseQuotaDialog;
}
void QQuickWebViewExperimental::setDatabaseQuotaDialog(QQmlComponent* databaseQuotaDialog)
{
Q_D(QQuickWebView);
if (d->databaseQuotaDialog == databaseQuotaDialog)
return;
d->databaseQuotaDialog = databaseQuotaDialog;
emit databaseQuotaDialogChanged();
}
QQmlComponent* QQuickWebViewExperimental::colorChooser() const
{
Q_D(const QQuickWebView);
return d->colorChooser;
}
void QQuickWebViewExperimental::setColorChooser(QQmlComponent* colorChooser)
{
Q_D(QQuickWebView);
if (d->colorChooser == colorChooser)
return;
d->colorChooser = colorChooser;
emit colorChooserChanged();
}
QString QQuickWebViewExperimental::userAgent() const
{
Q_D(const QQuickWebView);
WKRetainPtr<WKStringRef> ua = adoptWK(WKPageCopyCustomUserAgent(d->webPage.get()));
return WKStringCopyQString(ua.get());
}
void QQuickWebViewExperimental::setUserAgent(const QString& userAgent)
{
Q_D(QQuickWebView);
WKRetainPtr<WKStringRef> newUserAgent = adoptWK(WKStringCreateWithQString(userAgent));
WKRetainPtr<WKStringRef> currentUserAgent = adoptWK(WKPageCopyCustomUserAgent(d->webPage.get()));
if (WKStringIsEqual(newUserAgent.get(), currentUserAgent.get()))
return;
WKPageSetCustomUserAgent(d->webPage.get(), newUserAgent.get());
emit userAgentChanged();
}
int QQuickWebViewExperimental::deviceWidth() const
{
Q_D(const QQuickWebView);
return d->webPageProxy->pageGroup()->preferences()->deviceWidth();
}
void QQuickWebViewExperimental::setDeviceWidth(int value)
{
Q_D(QQuickWebView);
d->webPageProxy->pageGroup()->preferences()->setDeviceWidth(qMax(0, value));
emit deviceWidthChanged();
}
int QQuickWebViewExperimental::deviceHeight() const
{
Q_D(const QQuickWebView);
return d->webPageProxy->pageGroup()->preferences()->deviceHeight();
}
void QQuickWebViewExperimental::setDeviceHeight(int value)
{
Q_D(QQuickWebView);
d->webPageProxy->pageGroup()->preferences()->setDeviceHeight(qMax(0, value));
emit deviceHeightChanged();
}
void QQuickWebViewExperimental::evaluateJavaScript(const QString& script, const QJSValue& value)
{
JSCallbackClosure* closure = new JSCallbackClosure;
closure->receiver = this;
closure->value = value;
WKRetainPtr<WKStringRef> scriptString = adoptWK(WKStringCreateWithQString(script));
WKPageRunJavaScriptInMainFrame(d_ptr->webPage.get(), scriptString.get(), closure, javaScriptCallback);
}
void QQuickWebViewExperimental::findText(const QString& string, FindFlags options)
{
Q_D(QQuickWebView);
if (string.isEmpty()) {
WKPageHideFindUI(d->webPage.get());
return;
}
WKFindOptions wkOptions = kWKFindOptionsCaseInsensitive;
if (options & FindCaseSensitively)
wkOptions = wkOptions & ~kWKFindOptionsCaseInsensitive;
if (options & FindBackward)
wkOptions |= kWKFindOptionsBackwards;
if (options & FindWrapsAroundDocument)
wkOptions |= kWKFindOptionsWrapAround;
if (options & FindHighlightAllOccurrences)
wkOptions |= kWKFindOptionsShowHighlight;
WKRetainPtr<WKStringRef> str = adoptWK(WKStringCreateWithQString(string));
WKPageFindString(d->webPage.get(), str.get(), wkOptions, std::numeric_limits<unsigned>::max() - 1);
}
QList<QUrl> QQuickWebViewExperimental::userScripts() const
{
Q_D(const QQuickWebView);
return d->userScripts;
}
void QQuickWebViewExperimental::setUserScripts(const QList<QUrl>& userScripts)
{
Q_D(QQuickWebView);
if (d->userScripts == userScripts)
return;
d->userScripts = userScripts;
d->updateUserScripts();
emit userScriptsChanged();
}
QUrl QQuickWebViewExperimental::remoteInspectorUrl() const
{
#if ENABLE(INSPECTOR_SERVER)
return QUrl(WebInspectorServer::shared().inspectorUrlForPageID(d_ptr->webPageProxy->inspector()->remoteInspectionPageID()));
#else
return QUrl();
#endif
}
QQuickUrlSchemeDelegate* QQuickWebViewExperimental::schemeDelegates_At(QQmlListProperty<QQuickUrlSchemeDelegate>* property, int index)
{
const QObjectList children = property->object->children();
if (index < children.count())
return static_cast<QQuickUrlSchemeDelegate*>(children.at(index));
return 0;
}
void QQuickWebViewExperimental::schemeDelegates_Append(QQmlListProperty<QQuickUrlSchemeDelegate>* property, QQuickUrlSchemeDelegate *scheme)
{
if (!scheme->scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive)) {
qWarning("WARNING: The qrc scheme is reserved to be handled internally. The handler will be ignored.");
delete scheme;
return;
}
QObject* schemeParent = property->object;
scheme->setParent(schemeParent);
QQuickWebViewExperimental* webViewExperimental = qobject_cast<QQuickWebViewExperimental*>(property->object->parent());
if (!webViewExperimental)
return;
scheme->reply()->setWebViewExperimental(webViewExperimental);
QQuickWebViewPrivate* d = webViewExperimental->d_func();
d->webPageProxy->registerApplicationScheme(scheme->scheme());
}
int QQuickWebViewExperimental::schemeDelegates_Count(QQmlListProperty<QQuickUrlSchemeDelegate>* property)
{
return property->object->children().count();
}
void QQuickWebViewExperimental::schemeDelegates_Clear(QQmlListProperty<QQuickUrlSchemeDelegate>* property)
{
const QObjectList children = property->object->children();
for (int index = 0; index < children.count(); index++) {
QObject* child = children.at(index);
child->setParent(0);
delete child;
}
}
QQmlListProperty<QQuickUrlSchemeDelegate> QQuickWebViewExperimental::schemeDelegates()
{
return QQmlListProperty<QQuickUrlSchemeDelegate>(schemeParent, 0,
QQuickWebViewExperimental::schemeDelegates_Append,
QQuickWebViewExperimental::schemeDelegates_Count,
QQuickWebViewExperimental::schemeDelegates_At,
QQuickWebViewExperimental::schemeDelegates_Clear);
}
void QQuickWebViewExperimental::invokeApplicationSchemeHandler(PassRefPtr<QtRefCountedNetworkRequestData> request)
{
RefPtr<QtRefCountedNetworkRequestData> req = request;
if (req->data().m_scheme.startsWith("qrc", false)) {
QQuickQrcSchemeDelegate qrcDelegate(QUrl(QString(req->data().m_urlString)));
qrcDelegate.request()->setNetworkRequestData(req);
qrcDelegate.reply()->setNetworkRequestData(req);
qrcDelegate.reply()->setWebViewExperimental(this);
qrcDelegate.readResourceAndSend();
return;
}
const QObjectList children = schemeParent->children();
for (int index = 0; index < children.count(); index++) {
QQuickUrlSchemeDelegate* delegate = qobject_cast<QQuickUrlSchemeDelegate*>(children.at(index));
if (!delegate)
continue;
if (!delegate->scheme().compare(QString(req->data().m_scheme), Qt::CaseInsensitive)) {
delegate->request()->setNetworkRequestData(req);
delegate->reply()->setNetworkRequestData(req);
emit delegate->receivedRequest();
return;
}
}
}
void QQuickWebViewExperimental::sendApplicationSchemeReply(QQuickNetworkReply* reply)
{
d_ptr->webPageProxy->sendApplicationSchemeReply(reply);
}
void QQuickWebViewExperimental::goForwardTo(int index)
{
d_ptr->navigationHistory->d->goForwardTo(index);
}
void QQuickWebViewExperimental::goBackTo(int index)
{
d_ptr->navigationHistory->d->goBackTo(index);
}
QWebKitTest* QQuickWebViewExperimental::test()
{
return m_test;
}
QQuickWebPage* QQuickWebViewExperimental::page()
{
return q_ptr->page();
}
QQuickWebView::QQuickWebView(QQuickItem* parent)
: QQuickFlickable(parent)
, d_ptr(createPrivateObject(this))
{
Q_D(QQuickWebView);
d->initialize();
}
QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent)
: QQuickFlickable(parent)
, d_ptr(createPrivateObject(this))
{
Q_D(QQuickWebView);
d->initialize(contextRef, pageGroupRef);
}
QQuickWebView::~QQuickWebView()
{
}
QQuickWebPage* QQuickWebView::page()
{
Q_D(QQuickWebView);
return d->pageView.data();
}
void QQuickWebView::goBack()
{
Q_D(QQuickWebView);
WKPageGoBack(d->webPage.get());
}
void QQuickWebView::goForward()
{
Q_D(QQuickWebView);
WKPageGoForward(d->webPage.get());
}
void QQuickWebView::stop()
{
Q_D(QQuickWebView);
WKPageStopLoading(d->webPage.get());
}
void QQuickWebView::reload()
{
Q_D(QQuickWebView);
WebFrameProxy* mainFrame = d->webPageProxy->mainFrame();
if (mainFrame && !mainFrame->unreachableURL().isEmpty() && mainFrame->url() != blankURL()) {
d->webPageProxy->loadURL(mainFrame->unreachableURL());
return;
}
WKPageReloadFromOrigin(d->webPage.get());
}
QUrl QQuickWebView::url() const
{
Q_D(const QQuickWebView);
return QUrl(d->m_currentUrl);
}
void QQuickWebView::setUrl(const QUrl& url)
{
Q_D(QQuickWebView);
if (url.isEmpty())
return;
WKRetainPtr<WKURLRef> u = adoptWK(WKURLCreateWithQUrl(url));
WKPageLoadURL(d->webPage.get(), u.get());
emitUrlChangeIfNeeded();
}
void QQuickWebView::emitUrlChangeIfNeeded()
{
Q_D(QQuickWebView);
QString activeUrl = d->webPageProxy->activeURL();
if (activeUrl != d->m_currentUrl) {
d->m_currentUrl = activeUrl;
emit urlChanged();
}
}
QUrl QQuickWebView::icon() const
{
Q_D(const QQuickWebView);
return d->m_iconUrl;
}
int QQuickWebView::loadProgress() const
{
Q_D(const QQuickWebView);
return d->loadProgress();
}
bool QQuickWebView::canGoBack() const
{
Q_D(const QQuickWebView);
return WKPageCanGoBack(d->webPage.get());
}
bool QQuickWebView::canGoForward() const
{
Q_D(const QQuickWebView);
return WKPageCanGoForward(d->webPage.get());
}
bool QQuickWebView::loading() const
{
Q_D(const QQuickWebView);
WKFrameRef mainFrame = WKPageGetMainFrame(d->webPage.get());
return mainFrame && !(kWKFrameLoadStateFinished == WKFrameGetFrameLoadState(mainFrame));
}
QPointF QQuickWebView::mapToWebContent(const QPointF& pointInViewCoordinates) const
{
Q_D(const QQuickWebView);
return d->pageView->transformFromItem().map(pointInViewCoordinates);
}
QRectF QQuickWebView::mapRectToWebContent(const QRectF& rectInViewCoordinates) const
{
Q_D(const QQuickWebView);
return d->pageView->transformFromItem().mapRect(rectInViewCoordinates);
}
QPointF QQuickWebView::mapFromWebContent(const QPointF& pointInCSSCoordinates) const
{
Q_D(const QQuickWebView);
return d->pageView->transformToItem().map(pointInCSSCoordinates);
}
QRectF QQuickWebView::mapRectFromWebContent(const QRectF& rectInCSSCoordinates) const
{
Q_D(const QQuickWebView);
return d->pageView->transformToItem().mapRect(rectInCSSCoordinates);
}
QString QQuickWebView::title() const
{
Q_D(const QQuickWebView);
WKRetainPtr<WKStringRef> t = adoptWK(WKPageCopyTitle(d->webPage.get()));
return WKStringCopyQString(t.get());
}
QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const
{
Q_D(const QQuickWebView);
const EditorState& state = d->webPageProxy->editorState();
switch(property) {
case Qt::ImCursorRectangle:
return QRectF(state.cursorRect);
case Qt::ImFont:
return QVariant();
case Qt::ImCursorPosition:
return QVariant(static_cast<int>(state.cursorPosition));
case Qt::ImAnchorPosition:
return QVariant(static_cast<int>(state.anchorPosition));
case Qt::ImSurroundingText:
return QString(state.surroundingText);
case Qt::ImCurrentSelection:
return QString(state.selectedText);
case Qt::ImMaximumTextLength:
return QVariant(); case Qt::ImHints:
return int(Qt::InputMethodHints(state.inputMethodHints));
default:
return QQuickFlickable::inputMethodQuery(property);
}
}
QQuickWebViewExperimental* QQuickWebView::experimental() const
{
Q_D(const QQuickWebView);
return d->experimental;
}
void QQuickWebView::platformInitialize()
{
JSC::initializeThreading();
WTF::initializeMainThread();
}
bool QQuickWebView::childMouseEventFilter(QQuickItem* item, QEvent* event)
{
if (!isVisible() || !isEnabled())
return false;
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
return false;
default:
ASSERT(event->type() == QEvent::UngrabMouse);
break;
}
return QQuickFlickable::childMouseEventFilter(item, event);
}
void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
{
Q_D(QQuickWebView);
QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
if (newGeometry.size() != oldGeometry.size())
d->updateViewportSize();
}
void QQuickWebView::componentComplete()
{
Q_D(QQuickWebView);
QQuickFlickable::componentComplete();
d->onComponentComplete();
d->updateViewportSize();
}
void QQuickWebView::keyPressEvent(QKeyEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleKeyPressEvent(event);
}
void QQuickWebView::keyReleaseEvent(QKeyEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleKeyReleaseEvent(event);
}
void QQuickWebView::inputMethodEvent(QInputMethodEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleInputMethodEvent(event);
}
void QQuickWebView::focusInEvent(QFocusEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleFocusInEvent(event);
}
void QQuickWebView::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QQuickWebView);
if (change == ItemActiveFocusHasChanged) {
bool focus = value.boolValue;
if (!focus)
d->pageEventHandler->handleFocusLost();
}
QQuickFlickable::itemChange(change, value);
}
void QQuickWebView::touchEvent(QTouchEvent* event)
{
Q_D(QQuickWebView);
bool lockingDisabled = flickableDirection() != AutoFlickDirection
|| event->touchPoints().size() != 1
|| width() >= contentWidth()
|| height() >= contentHeight();
if (!lockingDisabled)
d->axisLocker.update(event);
else
d->axisLocker.reset();
forceActiveFocus();
d->pageEventHandler->handleTouchEvent(event);
}
void QQuickWebView::mousePressEvent(QMouseEvent* event)
{
Q_D(QQuickWebView);
forceActiveFocus();
d->handleMouseEvent(event);
}
void QQuickWebView::mouseMoveEvent(QMouseEvent* event)
{
Q_D(QQuickWebView);
d->handleMouseEvent(event);
}
void QQuickWebView::mouseReleaseEvent(QMouseEvent* event)
{
Q_D(QQuickWebView);
d->handleMouseEvent(event);
}
void QQuickWebView::mouseDoubleClickEvent(QMouseEvent* event)
{
Q_D(QQuickWebView);
forceActiveFocus();
d->handleMouseEvent(event);
}
void QQuickWebView::wheelEvent(QWheelEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleWheelEvent(event);
}
void QQuickWebView::hoverEnterEvent(QHoverEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleHoverMoveEvent(event);
}
void QQuickWebView::hoverMoveEvent(QHoverEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleHoverMoveEvent(event);
}
void QQuickWebView::hoverLeaveEvent(QHoverEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleHoverLeaveEvent(event);
}
void QQuickWebView::dragMoveEvent(QDragMoveEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleDragMoveEvent(event);
}
void QQuickWebView::dragEnterEvent(QDragEnterEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleDragEnterEvent(event);
}
void QQuickWebView::dragLeaveEvent(QDragLeaveEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleDragLeaveEvent(event);
}
void QQuickWebView::dropEvent(QDropEvent* event)
{
Q_D(QQuickWebView);
d->pageEventHandler->handleDropEvent(event);
}
bool QQuickWebView::event(QEvent* ev)
{
return QQuickFlickable::event(ev);
}
WKPageRef QQuickWebView::pageRef() const
{
Q_D(const QQuickWebView);
return d->webPage.get();
}
QPointF QQuickWebView::contentPos() const
{
Q_D(const QQuickWebView);
return d->contentPos();
}
void QQuickWebView::setContentPos(const QPointF& pos)
{
Q_D(QQuickWebView);
if (pos == contentPos())
return;
d->setContentPos(pos);
}
void QQuickWebView::handleFlickableMousePress(const QPointF& position, qint64 eventTimestampMillis)
{
Q_D(QQuickWebView);
d->axisLocker.setReferencePosition(position);
QMouseEvent mouseEvent(QEvent::MouseButtonPress, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
mouseEvent.setTimestamp(eventTimestampMillis);
QQuickFlickable::mousePressEvent(&mouseEvent);
}
void QQuickWebView::handleFlickableMouseMove(const QPointF& position, qint64 eventTimestampMillis)
{
Q_D(QQuickWebView);
QMouseEvent mouseEvent(QEvent::MouseMove, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
mouseEvent.setTimestamp(eventTimestampMillis);
QQuickFlickable::mouseMoveEvent(&mouseEvent);
}
void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 eventTimestampMillis)
{
Q_D(QQuickWebView);
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
d->axisLocker.reset();
mouseEvent.setTimestamp(eventTimestampMillis);
QQuickFlickable::mouseReleaseEvent(&mouseEvent);
}
void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl, const QUrl& unreachableUrl)
{
Q_D(QQuickWebView);
WKRetainPtr<WKStringRef> htmlRef = adoptWK(WKStringCreateWithQString(html));
WKRetainPtr<WKURLRef> baseUrlRef = adoptWK(WKURLCreateWithQUrl(baseUrl));
WKRetainPtr<WKURLRef> unreachableUrlRef = adoptWK(WKURLCreateWithQUrl(unreachableUrl));
if (unreachableUrl.isValid())
WKPageLoadAlternateHTMLString(d->webPage.get(), htmlRef.get(), baseUrlRef.get(), unreachableUrlRef.get());
else
WKPageLoadHTMLString(d->webPage.get(), htmlRef.get(), baseUrlRef.get());
}
qreal QQuickWebView::zoomFactor() const
{
Q_D(const QQuickWebView);
return d->zoomFactor();
}
void QQuickWebView::setZoomFactor(qreal factor)
{
Q_D(QQuickWebView);
d->setZoomFactor(factor);
}
void QQuickWebView::runJavaScriptInMainFrame(const QString &script, QObject *receiver, const char *method)
{
Q_D(QQuickWebView);
JSCallbackClosure* closure = new JSCallbackClosure;
closure->receiver = receiver;
closure->method = method;
WKRetainPtr<WKStringRef> scriptString = adoptWK(WKStringCreateWithQString(script));
WKPageRunJavaScriptInMainFrame(d->webPage.get(), scriptString.get(), closure, javaScriptCallback);
}
bool QQuickWebView::allowAnyHTTPSCertificateForLocalHost() const
{
Q_D(const QQuickWebView);
return d->m_allowAnyHTTPSCertificateForLocalHost;
}
void QQuickWebView::setAllowAnyHTTPSCertificateForLocalHost(bool allow)
{
Q_D(QQuickWebView);
d->m_allowAnyHTTPSCertificateForLocalHost = allow;
}
void QQuickWebViewPrivate::didFindString(WKPageRef, WKStringRef, unsigned matchCount, const void* clientInfo)
{
QQuickWebView* q = toQQuickWebViewPrivate(clientInfo)->q_ptr;
emit q->experimental()->textFound(matchCount);
}
void QQuickWebViewPrivate::didFailToFindString(WKPageRef page, WKStringRef string, const void* clientInfo)
{
QQuickWebViewPrivate::didFindString(page, string, 0, clientInfo);
}
#include "moc_qquickwebview_p.cpp"