diff options
Diffstat (limited to 'src/core/web_engine_context.cpp')
-rw-r--r-- | src/core/web_engine_context.cpp | 860 |
1 files changed, 530 insertions, 330 deletions
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 5c125bb8f..94110d51c 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -1,112 +1,89 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 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 #include "web_engine_context.h" #include <math.h> +#include <QtGui/private/qrhi_p.h> #include "base/base_switches.h" +#include "base/functional/bind.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/run_loop.h" -#include "base/task/post_task.h" +#include "base/strings/string_split.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/media/webrtc/webrtc_log_uploader.h" +#endif #include "chrome/common/chrome_switches.h" +#include "content/common/process_visibility_tracker.h" #include "content/gpu/gpu_child_thread.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/compositor/viz_process_transport_factory.h" #include "components/viz/host/host_frame_sink_manager.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "chrome/browser/printing/print_job_manager.h" -#include "components/printing/browser/features.h" #endif #include "components/discardable_memory/service/discardable_shared_memory_manager.h" +#include "components/download/public/common/download_task_runner.h" #include "components/viz/common/features.h" #include "components/web_cache/browser/web_cache_manager.h" -#include "content/app/service_manager_environment.h" +#include "content/app/mojo_ipc_support.h" #include "content/browser/devtools/devtools_http_handler.h" +#include "content/browser/gpu/gpu_main_thread_factory.h" +#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/scheduler/browser_task_executor.h" #include "content/browser/startup_data_impl.h" #include "content/browser/startup_helper.h" +#include "content/browser/utility_process_host.h" +#include "content/gpu/in_process_gpu_thread.h" #include "content/public/app/content_main.h" #include "content/public/app/content_main_runner.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#if QT_CONFIG(webengine_pepper_plugins) #include "content/public/browser/plugin_service.h" +#endif #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" -#include "content/public/common/network_service_util.h" +#include "content/renderer/in_process_renderer_thread.h" +#include "content/utility/in_process_utility_thread.h" #include "gpu/command_buffer/service/gpu_switches.h" -#include "gpu/command_buffer/service/sync_point_manager.h" +#include "gpu/config/gpu_finch_features.h" #include "media/audio/audio_manager.h" #include "media/base/media_switches.h" #include "mojo/core/embedder/embedder.h" #include "net/base/port_util.h" -#include "ppapi/buildflags/buildflags.h" +#include "sandbox/policy/switches.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" #include "services/network/public/mojom/network_context.mojom.h" -#include "services/service_manager/sandbox/switches.h" #include "services/tracing/public/cpp/trace_startup.h" #include "services/tracing/public/cpp/tracing_features.h" #include "third_party/blink/public/common/features.h" #include "ui/base/ui_base_features.h" #include "ui/events/event_switches.h" #include "ui/native_theme/native_theme_features.h" +#include "ui/gl/gl_utils.h" #include "ui/gl/gl_switches.h" -#if defined(OS_WIN) +#if defined(Q_OS_WIN) #include "sandbox/win/src/sandbox_types.h" #include "content/public/app/sandbox_helper_win.h" -#endif // OS_WIN +#endif // Q_OS_WIN #if defined(Q_OS_MACOS) -#include "base/mac/foundation_util.h" +#include "base/apple/foundation_util.h" #endif #if QT_CONFIG(accessibility) @@ -129,15 +106,17 @@ #include <QMutex> #include <QOffscreenSurface> #if QT_CONFIG(opengl) -# include <QOpenGLContext> -# include <qopenglcontext_platform.h> +#include <QOpenGLContext> +#include <qopenglcontext_platform.h> #endif #include <QQuickWindow> +#include <QRegularExpression> #include <QStringList> #include <QSurfaceFormat> #include <QNetworkProxy> #include <QtGui/qpa/qplatformintegration.h> #include <QtGui/private/qguiapplication_p.h> +#include <QtQuick/private/qsgrhisupport_p.h> #include <QLoggingCategory> #if QT_CONFIG(opengl) @@ -146,28 +125,24 @@ Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); QT_END_NAMESPACE #endif +#define STRINGIFY_LITERAL(x) #x +#define STRINGIFY_EXPANDED(x) STRINGIFY_LITERAL(x) + namespace QtWebEngineCore { -#if QT_CONFIG(opengl) -static bool usingANGLE() -{ -#if defined(Q_OS_WIN) - if (qt_gl_global_share_context()) - return qt_gl_global_share_context()->isOpenGLES(); - return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES; -#else - return false; -#endif -} +Q_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext") -static bool usingDefaultSGBackend() +static bool usingSupportedSGBackend() { - if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL) + if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL + && QQuickWindow::graphicsApi() != QSGRendererInterface::Vulkan + && QQuickWindow::graphicsApi() != QSGRendererInterface::Metal + && QQuickWindow::graphicsApi() != QSGRendererInterface::Direct3D11) return false; const QStringList args = QGuiApplication::arguments(); - //folow logic from contextFactory in src/quick/scenegraph/qsgcontextplugin.cpp + // follow the logic from contextFactory in src/quick/scenegraph/qsgcontextplugin.cpp QString device = QQuickWindow::sceneGraphBackend(); for (int index = 0; index < args.count(); ++index) { @@ -182,120 +157,257 @@ static bool usingDefaultSGBackend() if (device.isEmpty()) device = qEnvironmentVariable("QMLSCENE_DEVICE"); - return device.isEmpty(); + return device.isEmpty() || device == QLatin1String("rhi"); } +#if QT_CONFIG(opengl) bool usingSoftwareDynamicGL() { + const char openGlVar[] = "QT_OPENGL"; if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL)) return true; + + if (qEnvironmentVariableIsSet(openGlVar)) { + const QByteArray requested = qgetenv(openGlVar); + if (requested == "software") + return true; + } #if defined(Q_OS_WIN) HMODULE handle = QNativeInterface::QWGLContext::openGLModuleHandle(); wchar_t path[MAX_PATH]; DWORD size = GetModuleFileName(handle, path, MAX_PATH); QFileInfo openGLModule(QString::fromWCharArray(path, size)); - return openGLModule.fileName() == QLatin1String("opengl32sw.dll"); + return openGLModule.fileName().contains(QLatin1String("opengl32sw"),Qt::CaseInsensitive); #else return false; #endif } -static const char *getGLType(bool enableGLSoftwareRendering) +static bool openGLPlatformSupport() { - const char *glType = nullptr; - const bool tryGL = (usingDefaultSGBackend() && !usingSoftwareDynamicGL() - && QGuiApplicationPrivate::platformIntegration()->hasCapability( - QPlatformIntegration::OpenGL)) - || enableGLSoftwareRendering; - if (tryGL) { - if (!qt_gl_global_share_context() || !qt_gl_global_share_context()->isValid()) { - qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context " - "creation failed."); - } else { - const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format(); - switch (sharedFormat.renderableType()) { - case QSurfaceFormat::OpenGL: - glType = gl::kGLImplementationDesktopName; - // Check if Core profile was requested and is supported. - if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) { -#ifdef Q_OS_MACOS - glType = gl::kGLImplementationCoreProfileName; + return QGuiApplicationPrivate::platformIntegration()->hasCapability( + QPlatformIntegration::OpenGL); +} + +static std::string getGLType(bool enableGLSoftwareRendering, bool disableGpu) +{ + const bool tryGL = + usingSupportedSGBackend() && !usingSoftwareDynamicGL() && openGLPlatformSupport(); + if (disableGpu || (!tryGL && !enableGLSoftwareRendering)) + return gl::kGLImplementationDisabledName; + +#if defined(Q_OS_MACOS) + return gl::kGLImplementationANGLEName; #else - qWarning("An OpenGL Core Profile was requested, but it is not supported " - "on the current platform. Falling back to a non-Core profile. " - "Note that this might cause rendering issues."); +#if defined(Q_OS_WIN) + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11 + || QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { + return gl::kGLImplementationANGLEName; + } #endif - } - break; - case QSurfaceFormat::OpenGLES: - glType = usingANGLE() ? gl::kGLImplementationANGLEName - : gl::kGLImplementationEGLName; - break; - case QSurfaceFormat::OpenVG: - case QSurfaceFormat::DefaultRenderableType: - default: - // Shared contex created but no rederable type set. - qWarning("Unsupported rendering surface format. Please open bug report at " - "https://bugreports.qt.io"); - } + + if (!qt_gl_global_share_context() || !qt_gl_global_share_context()->isValid()) { + qWarning("WebEngineContext is used before QtWebEngineQuick::initialize() or OpenGL context " + "creation failed."); + return gl::kGLImplementationDisabledName; + } + + const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format(); + + switch (sharedFormat.renderableType()) { + case QSurfaceFormat::OpenGL: + if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) { + qWarning("An OpenGL Core Profile was requested, but it is not supported " + "on the current platform. Falling back to a non-Core profile. " + "Note that this might cause rendering issues."); } + return gl::kGLImplementationDesktopName; + case QSurfaceFormat::OpenGLES: + return gl::kGLImplementationEGLName; + case QSurfaceFormat::OpenVG: + case QSurfaceFormat::DefaultRenderableType: + default: + // Shared contex created but no rederable type set. + qWarning("Unsupported rendering surface format. Please open bug report at " + "https://bugreports.qt.io"); } - return glType; + + return gl::kGLImplementationDisabledName; +#endif // defined(Q_OS_MACOS) } #else -static cont char *getGLType(bool enableGLSoftwareRendering) +static std::string getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu) { - return nullptr; + if (disableGpu) + return gl::kGLImplementationDisabledName; +#if defined(Q_OS_MACOS) + return gl::kGLImplementationANGLEName; +#elif defined(Q_OS_WIN) + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11 + || QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { + return gl::kGLImplementationANGLEName; + } +#endif + return gl::kGLImplementationDisabledName; } #endif // QT_CONFIG(opengl) -#if QT_CONFIG(webengine_pepper_plugins) -void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) +static std::string getVulkanType(base::CommandLine *cmd) { +#if QT_CONFIG(webengine_vulkan) + if (cmd->HasSwitch(switches::kUseVulkan)) + return cmd->GetSwitchValueASCII(switches::kUseVulkan); +#endif + + return "disabled"; } + +static std::string getAngleType(const std::string &glType, base::CommandLine *cmd) +{ + if (glType == gl::kGLImplementationANGLEName) { + if (cmd->HasSwitch(switches::kUseANGLE)) + return cmd->GetSwitchValueASCII(switches::kUseANGLE); + +#if defined(Q_OS_WIN) + return gl::kANGLEImplementationD3D11Name; +#elif defined(Q_OS_MACOS) + return gl::kANGLEImplementationMetalName; +#else + return gl::kANGLEImplementationDefaultName; #endif + } + + return "disabled"; +} -static void logContext(const char *glType, base::CommandLine *cmd) +static quint64 getGPUVendorId() { - QLoggingCategory webEngineContextLog("qt.webenginecontext"); - if (webEngineContextLog.isInfoEnabled()) { - const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format(); - const auto profile = QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey( - sharedFormat.profile()); - const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey( - sharedFormat.renderableType()); - const base::CommandLine::SwitchMap switch_map = cmd->GetSwitches(); - QStringList params; - for (const auto &pair : switch_map) - params << " * " << toQt(pair.first) - << toQt(pair.second) << "\n"; - qCInfo(webEngineContextLog, - "\n\nGLImplementation: %s\n" - "Surface Type: %s\n" - "Surface Profile: %s\n" - "Surface Version: %d.%d\n" - "Using Default SG Backend: %s\n" - "Using Software Dynamic GL: %s\n" - "Using Angle: %s\n\n" - "Init Parameters:\n %s", - glType, type, profile, sharedFormat.majorVersion(), sharedFormat.minorVersion(), - usingDefaultSGBackend() ? "yes" : "no", usingSoftwareDynamicGL() ? "yes" : "no", - usingANGLE() ? "yes" : "no", qPrintable(params.join(" "))); +#if QT_CONFIG(webengine_vulkan) + QVulkanInstance vulkanInstance; + vulkanInstance.setApiVersion(QVersionNumber(1, 1)); + if (vulkanInstance.create()) { + QRhiVulkanInitParams params; + params.inst = &vulkanInstance; + QScopedPointer<QRhi> rhi(QRhi::create(QRhi::Vulkan, ¶ms, QRhi::Flags(), nullptr)); + return rhi->driverInfo().vendorId; } +#endif + + return 0; } #if defined(Q_OS_WIN) -sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterfaceInfo *info) -{ - static sandbox::SandboxInterfaceInfo *g_info = nullptr; - if (info) { - Q_ASSERT(g_info == nullptr); - g_info = info; +static QString getAdapterLuid() { + static const bool preferSoftwareDevice = qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER"); + QRhiD3D11InitParams rhiParams; + QRhi::Flags flags; + if (preferSoftwareDevice) { + flags |= QRhi::PreferSoftwareRenderer; + } + QScopedPointer<QRhi> rhi(QRhi::create(QRhi::D3D11,&rhiParams,flags,nullptr)); + // mimic what QSGRhiSupport and QBackingStoreRhi does + if (!rhi && !preferSoftwareDevice) { + flags |= QRhi::PreferSoftwareRenderer; + rhi.reset(QRhi::create(QRhi::D3D11, &rhiParams, flags)); + } + if (rhi) { + const QRhiD3D11NativeHandles *handles = + static_cast<const QRhiD3D11NativeHandles *>(rhi->nativeHandles()); + Q_ASSERT(handles); + return QString("%1,%2").arg(handles->adapterLuidHigh).arg(handles->adapterLuidLow); + } else { + return QString(); } - return g_info; } #endif +#if QT_CONFIG(webengine_pepper_plugins) +void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) +{ +} +#endif + +static void logContext(const std::string &glType, base::CommandLine *cmd) +{ + if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) { + QStringList log; + log << "\n"; + + log << "Chromium GL Backend:" << glType.c_str() << "\n"; + log << "Chromium ANGLE Backend:" << getAngleType(glType, cmd).c_str() << "\n"; + log << "Chromium Vulkan Backend:" << getVulkanType(cmd).c_str() << "\n"; + log << "\n"; + + log << "QSG RHI Backend:" << QSGRhiSupport::instance()->rhiBackendName() << "\n"; + log << "QSG RHI Backend Supported:" << (usingSupportedSGBackend() ? "yes" : "no") << "\n"; + log << "GPU Vendor:"; + if (quint64 vendorId = getGPUVendorId()) { + switch (vendorId) { + case 0x1002: + log << "AMD"; + break; + case 0x10DE: + log << "NVIDIA"; + break; + case 0x8086: + log << "Intel"; + break; + case 0x1010: + log << "ImgTec"; + break; + case 0x13B5: + log << "ARM"; + break; + case 0x5143: + log << "Qualcomm"; + break; + default: + break; + } + log << QString("(0x%1)\n").arg(vendorId, 0, 16); + } else { + log << "Unable to detect\n"; + } + log << "\n"; + +#if QT_CONFIG(opengl) +#if defined(USE_OZONE) + log << "Using GLX:" << (GLContextHelper::getGlxPlatformInterface() ? "yes" : "no") << "\n"; + log << "Using EGL:" << (GLContextHelper::getEglPlatformInterface() ? "yes" : "no") << "\n"; +#endif + log << "Using Shared GL:" << (qt_gl_global_share_context() ? "yes" : "no") << "\n"; + if (qt_gl_global_share_context()) { + log << "Using Software Dynamic GL:" << (usingSoftwareDynamicGL() ? "yes" : "no") + << "\n"; + + const QSurfaceFormat sharedFormat = qt_gl_global_share_context() + ? qt_gl_global_share_context()->format() + : QSurfaceFormat::defaultFormat(); + const auto profile = + QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey( + sharedFormat.profile()); + const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey( + sharedFormat.renderableType()); + log << "Surface Type:" << type << "\n"; + log << "Surface Profile:" << profile << "\n"; + log << "Surface Version:" + << QString("%1.%2") + .arg(sharedFormat.majorVersion()) + .arg(sharedFormat.minorVersion()) + << "\n"; + } + log << "\n"; +#endif // QT_CONFIG(opengl) + + log << "Init Parameters:\n"; + const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches(); + for (const auto &pair : switchMap) + log << " * " << toQt(pair.first) << toQt(pair.second) << "\n"; + + qCDebug(webEngineContextLog) << qPrintable(log.join(" ")); + } +} + extern std::unique_ptr<base::MessagePump> messagePumpFactory(); static void setupProxyPac(base::CommandLine *commandLine) @@ -319,26 +431,14 @@ static void setupProxyPac(base::CommandLine *commandLine) } } -static bool waitForViz = false; -static void completeVizCleanup() -{ - waitForViz = false; -} - static void cleanupVizProcess() { auto gpuChildThread = content::GpuChildThread::instance(); if (!gpuChildThread) return; - auto vizMain = gpuChildThread->viz_main(); - auto vizCompositorThreadRunner = vizMain->viz_compositor_thread_runner(); - if (!vizCompositorThreadRunner) - return; - waitForViz = true; content::GetHostFrameSinkManager()->SetConnectionLostCallback(base::DoNothing()); auto factory = static_cast<content::VizProcessTransportFactory*>(content::ImageTransportFactory::GetInstance()); factory->PrepareForShutDown(); - vizCompositorThreadRunner->CleanupForShutdown(base::BindOnce(&completeVizCleanup)); } static QStringList parseEnvCommandLine(const QString &cmdLine) @@ -389,7 +489,7 @@ static QStringList parseEnvCommandLine(const QString &cmdLine) scoped_refptr<QtWebEngineCore::WebEngineContext> WebEngineContext::m_handle; bool WebEngineContext::m_destroyed = false; - +bool WebEngineContext::m_closingDown = false; void WebEngineContext::destroyProfileAdapter() { if (content::RenderProcessHost::run_renderer_in_process()) { @@ -428,26 +528,31 @@ void WebEngineContext::removeProfileAdapter(ProfileAdapter *profileAdapter) m_profileAdapters.removeAll(profileAdapter); } +void WebEngineContext::flushMessages() +{ + if (!m_destroyed) { + base::MessagePump::Delegate *delegate = static_cast< + base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( + WebEngineContext::current()->m_runLoop->delegate_); + while (delegate->DoWork().is_immediate()) { } + } +} void WebEngineContext::destroy() { if (m_devtoolsServer) m_devtoolsServer->stop(); +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + if (m_webrtcLogUploader) + m_webrtcLogUploader->Shutdown(); +#endif - base::MessagePump::Delegate *delegate = - static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>( - m_runLoop->delegate_); // Normally the GPU thread is shut down when the GpuProcessHost is destroyed // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI // task runner is not working anymore so we need to do this earlier. cleanupVizProcess(); - while (waitForViz) { - while (delegate->DoWork().is_immediate()) { } - QThread::msleep(50); - } - destroyGpuProcess(); // Flush the UI message loop before quitting. - while (delegate->DoWork().is_immediate()) { } + flushMessages(); #if QT_CONFIG(webengine_printing_and_pdf) // Kill print job manager early as it has a content::NotificationRegistrar @@ -469,7 +574,7 @@ void WebEngineContext::destroy() // Handle any events posted by browser-context shutdown. // This should deliver all nessesery calls of DeleteSoon from PostTask - while (delegate->DoWork().is_immediate()) { } + flushMessages(); m_devtoolsServer.reset(); m_runLoop->AfterRun(); @@ -480,8 +585,7 @@ void WebEngineContext::destroy() GLContextHelper::destroy(); // These would normally be in the content-runner, but we allocated them separately: - m_startupData.reset(); - m_serviceManagerEnvironment.reset(); + m_mojoIpcSupport.reset(); m_discardableSharedMemoryManager.reset(); // Destroying content-runner will force Chromium at_exit calls to run, and @@ -490,6 +594,10 @@ void WebEngineContext::destroy() // Drop the false reference. m_handle->Release(); + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + m_webrtcLogUploader.reset(); +#endif } WebEngineContext::~WebEngineContext() @@ -499,7 +607,6 @@ WebEngineContext::~WebEngineContext() Q_ASSERT(!m_devtoolsServer); Q_ASSERT(!m_browserRunner); Q_ASSERT(m_profileAdapters.isEmpty()); - delete s_syncPointManager.fetchAndStoreRelaxed(nullptr); } WebEngineContext *WebEngineContext::current() @@ -520,7 +627,7 @@ ProfileAdapter *WebEngineContext::createDefaultProfileAdapter() { Q_ASSERT(!m_destroyed); if (!m_defaultProfileAdapter) { - ProfileAdapter *profile = new ProfileAdapter(QStringLiteral("Default")); + ProfileAdapter *profile = new ProfileAdapter(); // profile when added to m_profileAdapters might be set default // profile in case of single-process if (!m_defaultProfileAdapter) @@ -544,6 +651,7 @@ void WebEngineContext::destroyContextPostRoutine() // Destroy WebEngineContext before its static pointer is zeroed and destructor called. // Before destroying MessageLoop via destroying BrowserMainRunner destructor // WebEngineContext's pointer is used. + m_closingDown = true; m_handle->destroy(); #if !defined(NDEBUG) if (!m_handle->HasOneRef()) @@ -572,36 +680,48 @@ ProxyAuthentication WebEngineContext::qProxyNetworkAuthentication(QString host, const static char kChromiumFlagsEnv[] = "QTWEBENGINE_CHROMIUM_FLAGS"; const static char kDisableSandboxEnv[] = "QTWEBENGINE_DISABLE_SANDBOX"; -const static char kDisableInProcGpuThread[] = "QTWEBENGINE_DISABLE_GPU_THREAD"; -// static -bool WebEngineContext::isGpuServiceOnUIThread() +static void initializeFeatureList(base::CommandLine *commandLine, std::vector<std::string> enableFeatures, std::vector<std::string> disableFeatures) { - static bool threadedGpu = -#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS) - QOpenGLContext::supportsThreadedOpenGL() && -#endif - !qEnvironmentVariableIsSet(kDisableInProcGpuThread); - return !threadedGpu; -} + std::string enableFeaturesString = base::JoinString(enableFeatures, ","); + if (commandLine->HasSwitch(switches::kEnableFeatures)) { + std::string commandLineEnableFeatures = commandLine->GetSwitchValueASCII(switches::kEnableFeatures); -static void appendToFeatureList(std::string &featureList, const char *feature) -{ - if (featureList.empty()) - featureList = feature; - else - featureList = featureList + "," + feature; -} + for (const std::string &enableFeature : base::SplitString(commandLineEnableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(disableFeatures.begin(), disableFeatures.end(), enableFeature); + if (it == disableFeatures.end()) + continue; -static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *featureSwitch, std::string feature) -{ - if (!commandLine->HasSwitch(featureSwitch)) { - commandLine->AppendSwitchASCII(featureSwitch, feature); - } else { - std::string featureList = commandLine->GetSwitchValueASCII(featureSwitch); - featureList = featureList + "," + feature; - commandLine->AppendSwitchASCII(featureSwitch, featureList); + qWarning("An unsupported feature has been enabled from command line: %s\n" + "The feature is enabled but there is no guarantee that it will work or not break QtWebEngine.", enableFeature.c_str()); + + // If a feature is disabled and enabled at the same time, then it will be disabled. + // Remove feature from the disable list to make it possible to override from command line. + disableFeatures.erase(it); + } + + enableFeaturesString = enableFeaturesString + "," + commandLineEnableFeatures; } + + std::string disableFeaturesString = base::JoinString(disableFeatures, ","); + if (commandLine->HasSwitch(switches::kDisableFeatures)) { + std::string commandLineDisableFeatures = commandLine->GetSwitchValueASCII(switches::kDisableFeatures); + + for (const std::string &disableFeature : base::SplitString(commandLineDisableFeatures, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto it = std::find(enableFeatures.begin(), enableFeatures.end(), disableFeature); + if (it == enableFeatures.end()) + continue; + + qWarning("An essential feature has been disabled from command line: %s\n" + "The feature is disabled but there is no guarantee that it will not break QtWebEngine.", disableFeature.c_str()); + } + + disableFeaturesString = disableFeaturesString + "," + commandLineDisableFeatures; + } + + commandLine->AppendSwitchASCII(switches::kEnableFeatures, enableFeaturesString); + commandLine->AppendSwitchASCII(switches::kDisableFeatures, disableFeaturesString); + base::FeatureList::InitializeInstance(enableFeaturesString, disableFeaturesString); } WebEngineContext::WebEngineContext() @@ -611,11 +731,11 @@ WebEngineContext::WebEngineContext() #if defined(Q_OS_MACOS) // The bundled handling is currently both completely broken in Chromium, // and unnecessary for us. - base::mac::SetOverrideAmIBundled(false); + base::apple::SetOverrideAmIBundled(false); #endif base::ThreadPoolInstance::Create("Browser"); - m_contentRunner.reset(content::ContentMainRunner::Create()); + m_contentRunner = content::ContentMainRunner::Create(); m_browserRunner = content::BrowserMainRunner::Create(); #ifdef Q_OS_LINUX @@ -628,7 +748,6 @@ WebEngineContext::WebEngineContext() // User might have registered "qrc" already with different options. QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc")); qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme - | QWebEngineUrlScheme::LocalAccessAllowed | QWebEngineUrlScheme::ViewSourceAllowed); QWebEngineUrlScheme::registerScheme(qrcScheme); } @@ -638,89 +757,99 @@ WebEngineContext::WebEngineContext() // Allow us to inject javascript like any webview toolkit. content::RenderFrameHost::AllowInjectingJavaScript(); - QStringList appArgs = QCoreApplication::arguments(); - bool useEmbeddedSwitches = false; -#if defined(QTWEBENGINE_EMBEDDED_SWITCHES) - useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches")); -#else - useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches")); -#endif + bool enableGLSoftwareRendering = false; + base::CommandLine *parsedCommandLine = + initCommandLine(useEmbeddedSwitches, enableGLSoftwareRendering); - base::CommandLine* parsedCommandLine = commandLine(); setupProxyPac(parsedCommandLine); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); - parsedCommandLine->AppendSwitchASCII(service_manager::switches::kApplicationName, QCoreApplication::applicationName().toUtf8().toPercentEncoding().toStdString()); + parsedCommandLine->AppendSwitchASCII(switches::kApplicationName, QCoreApplication::applicationName().toUtf8().toPercentEncoding().toStdString()); // Enable sandboxing on OS X and Linux (Desktop / Embedded) by default. bool disable_sandbox = qEnvironmentVariableIsSet(kDisableSandboxEnv); -#if defined(Q_OS_WIN) - disable_sandbox = true; // FIXME: Windows sandbox no longer works on CI, but works fine locally. -#endif if (!disable_sandbox) { #if defined(Q_OS_LINUX) - parsedCommandLine->AppendSwitch(service_manager::switches::kDisableSetuidSandbox); + parsedCommandLine->AppendSwitch(sandbox::policy::switches::kDisableSetuidSandbox); #endif } else { - parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); + parsedCommandLine->AppendSwitch(sandbox::policy::switches::kNoSandbox); qInfo() << "Sandboxing disabled by user."; } - parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); - // Do not advertise a feature we have removed at compile time parsedCommandLine->AppendSwitch(switches::kDisableSpeechAPI); - std::string disableFeatures; - std::string enableFeatures; - // Needed to allow navigations within pages that were set using setHtml(). One example is - // tst_QWebEnginePage::acceptNavigationRequest. - // This is deprecated behavior, and will be removed in a future Chromium version, as per - // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. - appendToFeatureList(enableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); + std::vector<std::string> disableFeatures; + std::vector<std::string> enableFeatures; - appendToFeatureList(enableFeatures, features::kTracingServiceInProcess.name); + enableFeatures.push_back(features::kNetworkServiceInProcess.name); + enableFeatures.push_back(features::kTracingServiceInProcess.name); - // The video-capture service is not functioning at this moment (since 69) - appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); - -#if defined(Q_OS_LINUX) - // broken and crashy (even upstream): - appendToFeatureList(disableFeatures, features::kFontSrcLocalMatching.name); -#endif - - // We don't support the skia renderer (enabled by default on Linux since 80) - appendToFeatureList(disableFeatures, features::kUseSkiaRenderer.name); + // When enabled, event.movement is calculated in blink instead of in browser. + disableFeatures.push_back(features::kConsolidatedMovementXY.name); - appendToFeatureList(disableFeatures, network::features::kDnsOverHttpsUpgrade.name); + // Avoid crashing when websites tries using this feature (since 83) + disableFeatures.push_back(features::kInstalledApp.name); - // When enabled, event.movement is calculated in blink instead of in browser. - appendToFeatureList(disableFeatures, features::kConsolidatedMovementXY.name); + // Not implemented but it overrides the devtools eyedropper + // Should be sync with kEyeDropper base::Feature + parsedCommandLine->AppendSwitchASCII(switches::kDisableBlinkFeatures, "EyeDropperAPI"); + disableFeatures.push_back(features::kEyeDropper.name); // Explicitly tell Chromium about default-on features we do not support - appendToFeatureList(disableFeatures, features::kBackgroundFetch.name); - appendToFeatureList(disableFeatures, features::kSmsReceiver.name); - appendToFeatureList(disableFeatures, features::kWebPayments.name); - appendToFeatureList(disableFeatures, features::kWebUsb.name); - appendToFeatureList(disableFeatures, media::kPictureInPicture.name); - - // Breaks current colordialog tests. - appendToFeatureList(disableFeatures, features::kFormControlsRefresh.name); + disableFeatures.push_back(features::kBackgroundFetch.name); + disableFeatures.push_back(features::kWebOTP.name); + disableFeatures.push_back(features::kWebPayments.name); + disableFeatures.push_back(features::kWebUsb.name); if (useEmbeddedSwitches) { // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc - appendToFeatureList(enableFeatures, features::kOverlayScrollbar.name); + enableFeatures.push_back(features::kOverlayScrollbar.name); parsedCommandLine->AppendSwitch(switches::kEnableViewport); - parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } - appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, disableFeatures); - appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, enableFeatures); - base::FeatureList::InitializeInstance( - parsedCommandLine->GetSwitchValueASCII(switches::kEnableFeatures), - parsedCommandLine->GetSwitchValueASCII(switches::kDisableFeatures)); +#if QT_CONFIG(webengine_vulkan) && defined(USE_OZONE) + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { + enableFeatures.push_back(features::kVulkan.name); + parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan, + switches::kVulkanImplementationNameNative); + const char deviceExtensionsVar[] = "QT_VULKAN_DEVICE_EXTENSIONS"; + QByteArrayList requiredDeviceExtensions = { "VK_KHR_external_memory_fd", + "VK_EXT_external_memory_dma_buf", + "VK_EXT_image_drm_format_modifier" }; + if (qEnvironmentVariableIsSet(deviceExtensionsVar)) { + QByteArrayList envExtList = qgetenv(deviceExtensionsVar).split(';'); + int found = 0; + for (const QByteArray &ext : requiredDeviceExtensions) { + if (envExtList.contains(ext)) + found++; + } + if (found != requiredDeviceExtensions.size()) { + qWarning().nospace() + << "Vulkan rendering may fail because " << deviceExtensionsVar + << " environment variable is already set but it doesn't contain" + << " some of the required Vulkan device extensions:\n" + << qPrintable(requiredDeviceExtensions.join('\n')); + } + } else { + qputenv(deviceExtensionsVar, requiredDeviceExtensions.join(';')); + } + } +#endif // QT_CONFIG(webengine_vulkan) && defined(USE_OZONE) + +#if defined(Q_OS_WIN) + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11 + || QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) { + const QString luid = getAdapterLuid(); + if (!luid.isEmpty()) + parsedCommandLine->AppendSwitchASCII(switches::kUseAdapterLuid, luid.toStdString()); + } +#endif + + initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures); GLContextHelper::initialize(); @@ -728,80 +857,91 @@ WebEngineContext::WebEngineContext() // bitmaps, use software rendering via software OpenGL. This might be less // performant, but at least provides WebGL support. // TODO(miklocek), check if this still works with latest chromium - const bool enableGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering")); - const char *glType = getGLType(enableGLSoftwareRendering); - - if (glType) { + const bool disableGpu = parsedCommandLine->HasSwitch(switches::kDisableGpu); + std::string glType; + if (parsedCommandLine->HasSwitch(switches::kUseGL)) + glType = parsedCommandLine->GetSwitchValueASCII(switches::kUseGL); + else { + glType = getGLType(enableGLSoftwareRendering, disableGpu); parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); - parsedCommandLine->AppendSwitch(switches::kInProcessGPU); + } + + parsedCommandLine->AppendSwitch(switches::kInProcessGPU); + + if (glType != gl::kGLImplementationDisabledName) { if (enableGLSoftwareRendering) { parsedCommandLine->AppendSwitch(switches::kDisableGpuRasterization); - parsedCommandLine->AppendSwitch(switches::kIgnoreGpuBlacklist); + parsedCommandLine->AppendSwitch(switches::kIgnoreGpuBlocklist); } - const QSurfaceFormat sharedFormat = QOpenGLContext::globalShareContext()->format(); - if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile) - parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); +#if QT_CONFIG(opengl) + if (glType != gl::kGLImplementationANGLEName) { + QOpenGLContext *shareContext = QOpenGLContext::globalShareContext(); + Q_ASSERT(shareContext); + const QSurfaceFormat sharedFormat = shareContext->format(); + if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile) + parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); #if defined(Q_OS_WIN) - // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create - // an OpenGL Core Profile context. If the switch is not set, it would always try to create a - // Core Profile context, even if Qt uses a legacy profile, which causes - // "Could not share GL contexts" warnings, because it's not possible to share between Core and - // legacy profiles. See GLContextWGL::Initialize(). - // Given that Desktop GL Core profile is not currently supported on Windows anyway, pass this - // switch to get rid of the warnings. - // - // The switch is also used to determine which version of OpenGL ES to use (2 or 3) when using - // ANGLE. - // If the switch is not set, Chromium will always try to create an ES3 context, even if Qt uses - // an ES2 context, which causes resource sharing issues (black screen), - // see gpu::gles2::GenerateGLContextAttribs(). - // Make sure to disable ES3 context creation when using ES2. - const bool isGLES2Context = QOpenGLContext::globalShareContext()->isOpenGLES() - && QOpenGLContext::globalShareContext()->format().majorVersion() == 2; - if (!usingANGLE() || isGLES2Context) - parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); + // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create + // an OpenGL Core Profile context. If the switch is not set, it would always try to create a + // Core Profile context, even if Qt uses a legacy profile, which causes + // "Could not share GL contexts" warnings, because it's not possible to share between Core and + // legacy profiles. See GLContextWGL::Initialize(). + if (sharedFormat.renderableType() == QSurfaceFormat::OpenGL + && sharedFormat.profile() != QSurfaceFormat::CoreProfile) { + gl::GlWorkarounds workarounds = gl::GetGlWorkarounds(); + workarounds.disable_es3gl_context = true; + gl::SetGlWorkarounds(workarounds); + } #endif - } else { + } +#endif //QT_CONFIG(opengl) + } else if (!disableGpu) { parsedCommandLine->AppendSwitch(switches::kDisableGpu); } + logContext(glType, parsedCommandLine); + registerMainThreadFactories(); content::ContentMainParams contentMainParams(m_mainDelegate.get()); -#if defined(OS_WIN) - contentMainParams.sandbox_info = staticSandboxInterfaceInfo(); - sandbox::SandboxInterfaceInfo sandbox_info = {0}; + contentMainParams.setup_signal_handlers = false; +#if defined(Q_OS_WIN) + contentMainParams.sandbox_info = QtWebEngineSandbox::staticSandboxInterfaceInfo(); + sandbox::SandboxInterfaceInfo sandbox_info = {nullptr}; if (!contentMainParams.sandbox_info) { content::InitializeSandboxInfo(&sandbox_info); contentMainParams.sandbox_info = &sandbox_info; } #endif - m_contentRunner->Initialize(contentMainParams); + m_contentRunner->Initialize(std::move(contentMainParams)); mojo::core::Configuration mojoConfiguration; mojoConfiguration.is_broker_process = true; mojo::core::Init(mojoConfiguration); - // This block mirrors ContentMainRunnerImpl::RunServiceManager(): - m_mainDelegate->PreCreateMainMessageLoop(); + // This block mirrors ContentMainRunnerImpl::RunBrowser(): + m_mainDelegate->PreBrowserMain(); base::MessagePump::OverrideMessagePumpForUIFactory(messagePumpFactory); content::BrowserTaskExecutor::Create(); - m_mainDelegate->PostEarlyInitialization(false); + m_mainDelegate->PostEarlyInitialization({}); content::StartBrowserThreadPool(); content::BrowserTaskExecutor::PostFeatureListSetup(); - tracing::InitTracingPostThreadPoolStartAndFeatureList(); - m_discardableSharedMemoryManager = std::make_unique<discardable_memory::DiscardableSharedMemoryManager>(); + tracing::InitTracingPostThreadPoolStartAndFeatureList(false); base::PowerMonitor::Initialize(std::make_unique<base::PowerMonitorDeviceSource>()); - m_serviceManagerEnvironment = std::make_unique<content::ServiceManagerEnvironment>(content::BrowserTaskExecutor::CreateIOThread()); - m_startupData = m_serviceManagerEnvironment->CreateBrowserStartupData(); + content::ProcessVisibilityTracker::GetInstance(); + m_discardableSharedMemoryManager = std::make_unique<discardable_memory::DiscardableSharedMemoryManager>(); + + m_mojoIpcSupport = std::make_unique<content::MojoIpcSupport>(content::BrowserTaskExecutor::CreateIOThread()); + download::SetIOTaskRunner(m_mojoIpcSupport->io_thread()->task_runner()); + std::unique_ptr<content::StartupData> startupData = m_mojoIpcSupport->CreateBrowserStartupData(); // Once the MessageLoop has been created, attach a top-level RunLoop. m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); - content::MainFunctionParams mainParams(*base::CommandLine::ForCurrentProcess()); - mainParams.startup_data = m_startupData.get(); - m_browserRunner->Initialize(mainParams); + content::MainFunctionParams mainParams(base::CommandLine::ForCurrentProcess()); + mainParams.startup_data = std::move(startupData); + m_browserRunner->Initialize(std::move(mainParams)); m_devtoolsServer.reset(new DevToolsServerQt()); m_devtoolsServer->start(); @@ -813,14 +953,7 @@ WebEngineContext::WebEngineContext() // Initialize WebCacheManager here to ensure its subscription to render process creation events. web_cache::WebCacheManager::GetInstance(); - base::ThreadRestrictions::SetIOAllowed(true); - - if (parsedCommandLine->HasSwitch(network::switches::kExplicitlyAllowedPorts)) { - std::string allowedPorts = parsedCommandLine->GetSwitchValueASCII(network::switches::kExplicitlyAllowedPorts); - net::SetExplicitlyAllowedPorts(allowedPorts); - } - -#if defined(OS_LINUX) +#if defined(Q_OS_LINUX) media::AudioManager::SetGlobalAppName(QCoreApplication::applicationName().toStdString()); #endif @@ -831,7 +964,7 @@ WebEngineContext::WebEngineContext() // be created from the FILE thread, and that GetPluginInfoArray is synchronous, it // can't loads plugins synchronously from the IO thread to serve the render process' request // and we need to make sure that it happened beforehand. - content::PluginService::GetInstance()->GetPlugins(base::Bind(&dummyGetPluginCallback)); + content::PluginService::GetInstance()->GetPlugins(base::BindOnce(&dummyGetPluginCallback)); #endif #if QT_CONFIG(webengine_printing_and_pdf) @@ -843,8 +976,6 @@ WebEngineContext::WebEngineContext() #endif content::WebUIControllerFactory::RegisterFactory(WebUIControllerFactoryQt::GetInstance()); - - logContext(glType, parsedCommandLine); } #if QT_CONFIG(webengine_printing_and_pdf) @@ -854,47 +985,116 @@ printing::PrintJobManager* WebEngineContext::getPrintJobManager() } #endif -static QMutex s_spmMutex; -QAtomicPointer<gpu::SyncPointManager> WebEngineContext::s_syncPointManager; - -gpu::SyncPointManager *WebEngineContext::syncPointManager() +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +WebRtcLogUploader *WebEngineContext::webRtcLogUploader() { - if (gpu::SyncPointManager *spm = s_syncPointManager.loadAcquire()) - return spm; - QMutexLocker lock(&s_spmMutex); - if (!s_syncPointManager) - s_syncPointManager.storeRelaxed(new gpu::SyncPointManager()); - return s_syncPointManager.loadRelaxed(); + if (!m_webrtcLogUploader) + m_webrtcLogUploader = std::make_unique<WebRtcLogUploader>(); + return m_webrtcLogUploader.get(); } +#endif + -base::CommandLine* WebEngineContext::commandLine() { - if (base::CommandLine::CreateEmpty()) { - base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); - QStringList appArgs = QCoreApplication::arguments(); - if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { - appArgs = appArgs.mid(0, 1); // Take application name and drop the rest - appArgs.append(parseEnvCommandLine(qEnvironmentVariable(kChromiumFlagsEnv))); +base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, + bool &enableGLSoftwareRendering) +{ + if (!base::CommandLine::CreateEmpty()) + qFatal("base::CommandLine has been initialized unexpectedly."); + + QStringList appArgs = QCoreApplication::arguments(); + if (appArgs.empty()) { + qFatal("Argument list is empty, the program name is not passed to QCoreApplication. " + "base::CommandLine cannot be properly initialized."); + } + + base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); + int index = appArgs.indexOf(QRegularExpression(QLatin1String("--webEngineArgs"), + QRegularExpression::CaseInsensitiveOption)); + if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { + appArgs = appArgs.mid(0, 1); // Take application name and drop the rest + appArgs.append(parseEnvCommandLine(qEnvironmentVariable(kChromiumFlagsEnv))); + if (index > -1) + qWarning("Note 'webEngineArgs' are overridden by QTWEBENGINE_CHROMIUM_FLAGS"); + } else { + if (index > -1) { + appArgs.erase(appArgs.begin() + 1, appArgs.begin() + index + 1); + } else { + appArgs = appArgs.mid(0, 1); } -#ifdef Q_OS_WIN - appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); + } +#if defined(QTWEBENGINE_EMBEDDED_SWITCHES) + useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches")); +#else + useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches")); #endif - appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); - appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); + enableGLSoftwareRendering = + appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); + appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); + appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); + + bool isRemoteDebugPort = + (-1 + != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-debugging-port=.*"), + QRegularExpression::CaseInsensitiveOption))) + || !qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING").isEmpty(); + bool isRemoteAllowOrigins = + (-1 + != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-allow-origins=.*"), + QRegularExpression::CaseInsensitiveOption))); + + if (isRemoteDebugPort && !isRemoteAllowOrigins) { + appArgs.append(QStringLiteral("--remote-allow-origins=*")); + qWarning("Added {--remote-allow-origins=*} to command-line arguments " + "to avoid web socket connection errors during remote debugging."); + } - base::CommandLine::StringVector argv; - argv.resize(appArgs.size()); + base::CommandLine::StringVector argv; + argv.resize(appArgs.size()); #if defined(Q_OS_WIN) - for (int i = 0; i < appArgs.size(); ++i) - argv[i] = toString16(appArgs[i]); + for (int i = 0; i < appArgs.size(); ++i) + argv[i] = appArgs[i].toStdWString(); #else - for (int i = 0; i < appArgs.size(); ++i) - argv[i] = appArgs[i].toStdString(); + for (int i = 0; i < appArgs.size(); ++i) + argv[i] = appArgs[i].toStdString(); #endif - parsedCommandLine->InitFromArgv(argv); - return parsedCommandLine; - } else { - return base::CommandLine::ForCurrentProcess(); - } + parsedCommandLine->InitFromArgv(argv); + + return parsedCommandLine; +} + +bool WebEngineContext::closingDown() +{ + return m_closingDown; +} + +void WebEngineContext::registerMainThreadFactories() +{ + content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); + content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); + content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); } } // namespace + +QT_BEGIN_NAMESPACE +const char *qWebEngineVersion() noexcept +{ + return STRINGIFY_EXPANDED(QTWEBENGINECORE_VERSION_STR); +} + +const char *qWebEngineProcessName() noexcept +{ + return STRINGIFY_EXPANDED(QTWEBENGINEPROCESS_NAME); +} + +const char *qWebEngineChromiumVersion() noexcept +{ + return STRINGIFY_EXPANDED(CHROMIUM_VERSION); +} + +const char *qWebEngineChromiumSecurityPatchVersion() noexcept +{ + return "122.0.6261.128"; // FIXME: Remember to update +} + +QT_END_NAMESPACE |