Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qwasmwebview_p.h"
++ #include <QtWebView/qwebview.h>
++ #include <QtWebView/qwebviewloadinginfo.h>
++
++ #include <QtCore/qmap.h>
++ #include <QtGui/qguiapplication.h>
++ #include <QtCore/qjsondocument.h>
++ #include <QtCore/qjsonobject.h>
++ #include <QtCore/qurl.h>
++ #include <QtCore/qdebug.h>
++
++ #include <QAbstractEventDispatcher>
++ #include <QThread>
++
++ #include <emscripten/emscripten.h>
++ #include <iostream>
++
++ QT_BEGIN_NAMESPACE
++
++ QWasmWebViewSettingsPrivate::QWasmWebViewSettingsPrivate() { }
++
++ bool QWasmWebViewSettingsPrivate::doTestAttribute(WebAttribute attribute) const
++ {
++ switch (attribute) {
++ case QWebViewSettings::WebAttribute::LocalStorageEnabled:
++ return localStorageEnabled();
++ case QWebViewSettings::WebAttribute::JavaScriptEnabled:
++ return javaScriptEnabled();
++ case QWebViewSettings::WebAttribute::AllowFileAccess:
++ return allowFileAccess();
++ case QWebViewSettings::WebAttribute::LocalContentCanAccessFileUrls:
++ return localContentCanAccessFileUrls();
++ }
++ return false;
++ }
++
++ void QWasmWebViewSettingsPrivate::doSetAttribute(WebAttribute attribute, bool value)
++ {
++ switch (attribute) {
++ case QWebViewSettings::WebAttribute::LocalStorageEnabled:
++ setLocalStorageEnabled(value);
++ break;
++ case QWebViewSettings::WebAttribute::JavaScriptEnabled:
++ setJavaScriptEnabled(value);
++ break;
++ case QWebViewSettings::WebAttribute::AllowFileAccess:
++ setAllowFileAccess(value);
++ break;
++ case QWebViewSettings::WebAttribute::LocalContentCanAccessFileUrls:
++ setLocalContentCanAccessFileUrls(value);
++ break;
++ }
++ }
++
++ bool QWasmWebViewSettingsPrivate::localStorageEnabled() const
++ {
++ qWarning("localStorageEnabled() not supported on this platform");
++ return false;
++ }
++
++ bool QWasmWebViewSettingsPrivate::javaScriptEnabled() const
++ {
++ qWarning("javaScriptEnabled() not supported on this platform");
++ return false;
++ }
++
++ bool QWasmWebViewSettingsPrivate::localContentCanAccessFileUrls() const
++ {
++ qWarning("localContentCanAccessFileUrls() not supported on this platform");
++ return false;
++ }
++
++ bool QWasmWebViewSettingsPrivate::allowFileAccess() const
++ {
++ qWarning("allowFileAccess() not supported on this platform");
++ return false;
++ }
++
++ void QWasmWebViewSettingsPrivate::setLocalContentCanAccessFileUrls(bool enabled)
++ {
++ Q_UNUSED(enabled);
++ qWarning("setLocalContentCanAccessFileUrls() not supported on this platform");
++ }
++
++ void QWasmWebViewSettingsPrivate::setJavaScriptEnabled(bool enabled)
++ {
++ Q_UNUSED(enabled);
++ qWarning("setJavaScriptEnabled() not supported on this platform");
++ }
++
++ void QWasmWebViewSettingsPrivate::setLocalStorageEnabled(bool enabled)
++ {
++ Q_UNUSED(enabled);
++ qWarning("setLocalStorageEnabled() not supported on this platform");
++ }
++
++ void QWasmWebViewSettingsPrivate::setAllowFileAccess(bool enabled)
++ {
++ Q_UNUSED(enabled);
++ qWarning("setAllowFileAccess() not supported on this platform");
++ }
++
++ QWasmWebViewPrivate::QWasmWebViewPrivate(QWebView *view) : QWebViewPrivate(view), m_window(view)
++ {
++ m_settings = new QWasmWebViewSettingsPrivate();
++ QMetaObject::invokeMethod(this, &QWasmWebViewPrivate::initializeIFrame, Qt::QueuedConnection);
++ }
++
++ QWasmWebViewPrivate::~QWasmWebViewPrivate() { }
++
++ QString QWasmWebViewPrivate::httpUserAgent() const
++ {
++ if (m_iframe)
++ return QString::fromStdString(
++ (*m_iframe)["contentWindow"]["navigator"]["userAgent"].as<std::string>());
++ return QString();
++ }
++
++ void QWasmWebViewPrivate::setHttpUserAgent(const QString &userAgent)
++ {
++ Q_UNUSED(userAgent);
++ qWarning("setHttpUserAgent() not supported on this platform");
++ }
++
++ QUrl QWasmWebViewPrivate::url() const
++ {
++ return m_currentUrl;
++ }
++
++ void QWasmWebViewPrivate::setUrl(const QUrl &url)
++ {
++ m_currentUrl = url;
++ if (m_iframe) {
++ (*m_iframe).call<void>("removeAttribute", emscripten::val("srcdoc"));
++ (*m_iframe).set("src", m_currentUrl.toString().toStdString());
++ }
++ }
++
++ void QWasmWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl)
++ {
++ if (!baseUrl.isEmpty())
++ qWarning("Base URLs for loadHtml() are not supported on this platform.");
++
++ if (m_iframe)
++ (*m_iframe).set("srcdoc", html.toStdString());
++ }
++
++ bool QWasmWebViewPrivate::canGoBack() const
++ {
++ qWarning("canGoBack() not supported on this platform");
++ return false;
++ }
++
++ void QWasmWebViewPrivate::goBack()
++ {
++ qWarning("goBack() not supported on this platform");
++ }
++
++ bool QWasmWebViewPrivate::canGoForward() const
++ {
++ qWarning("canGoForward() not supported on this platform");
++ return false;
++ }
++
++ void QWasmWebViewPrivate::goForward()
++ {
++ qWarning("goForward() not supported on this platform");
++ }
++
++ void QWasmWebViewPrivate::reload()
++ {
++ if (m_iframe) {
++ (*m_iframe)["contentWindow"]["location"].call<void>("reload");
++ setUrl(m_currentUrl);
++ // this order of operation is important, setting URL before reload()
++ // did not work, HTTP reload request was being cancelled by browser
++ }
++ }
++
++ void QWasmWebViewPrivate::stop()
++ {
++ qWarning("stop() not supported on this platform");
++ }
++
++ QString QWasmWebViewPrivate::title() const
++ {
++ if (m_iframe)
++ return QString::fromStdString(
++ (*m_iframe)["contentWindow"]["document"]["title"].as<std::string>());
++ return QString();
++ }
++
++ int QWasmWebViewPrivate::loadProgress() const
++ {
++ qWarning("loadProgress() not supported on this platform");
++ return 100;
++ }
++
++ bool QWasmWebViewPrivate::isLoading() const
++ {
++ qWarning("isLoading() not supported on this platform");
++ return false;
++ }
++
++ void QWasmWebViewPrivate::setCookie(const QString &domain, const QString &name,
++ const QString &value)
++ {
++ Q_UNUSED(domain);
++ Q_UNUSED(name);
++ Q_UNUSED(value);
++ qWarning("setCookie() not supported on this platform");
++ }
++
++ void QWasmWebViewPrivate::deleteCookie(const QString &domain, const QString &name)
++ {
++ Q_UNUSED(domain);
++ Q_UNUSED(name);
++ qWarning("deleteCookie() not supported on this platform");
++ }
++
++ void QWasmWebViewPrivate::deleteAllCookies()
++ {
++ qWarning("deleteAllCookies() not supported on this platform");
++ }
++
++ void QWasmWebViewPrivate::runJavaScript(const QString &script,
++ const std::function<void(const QVariant &)> &resultCallback)
++ {
++ Q_UNUSED(script);
++ Q_UNUSED(resultCallback);
++ qWarning("runJavaScript() not supported on this platform");
++ }
++
++ QWebViewSettingsPrivate *QWasmWebViewPrivate::settings() const
++ {
++ return m_settings;
++ }
++
++ // clang-format off
++ EM_JS(void, addResizeObservers, (emscripten::EM_VAL clientAreaHandle, emscripten::EM_VAL frameHandle), {
++ var clientArea = Emval.toValue(clientAreaHandle);
++ var frame = Emval.toValue(frameHandle);
++ const resizeObserver = new ResizeObserver((entries) => {
++ for (const entry of entries) {
++ frame.width = entry.contentBoxSize[0].inlineSize;
++ frame.height = entry.contentBoxSize[0].blockSize;
++ }
++ });
++ resizeObserver.observe(clientArea);
++ });
++ // clang-format on
++
++ void QWasmWebViewPrivate::initializeIFrame()
++ {
++ auto wasmWindow = dynamic_cast<QNativeInterface::Private::QWasmWindow *>(m_window->handle());
++ Q_ASSERT(wasmWindow);
++
++ auto document = wasmWindow->document();
++ auto clientArea = wasmWindow->clientArea();
++
++ m_iframe = document.call<emscripten::val>("createElement", emscripten::val("iframe"));
++ clientArea.call<void>("appendChild", *m_iframe);
++ (*m_iframe)["style"].set("position", "absolute");
++ (*m_iframe)["style"].set("border", "none");
++ (*m_iframe)["style"].set("top", "0px");
++ (*m_iframe)["style"].set("left", "0px");
++ addResizeObservers(clientArea.as_handle(), m_iframe.value().as_handle());
++
++ // NOTE: Make sure any pending url is set now.
++ setUrl(m_currentUrl);
++ }
++
++ QT_END_NAMESPACE