diff options
-rw-r--r-- | dist/changes-5.12.1 | 78 | ||||
-rw-r--r-- | src/core/api/qwebengineurlscheme.cpp | 33 | ||||
-rw-r--r-- | src/core/api/qwebengineurlscheme.h | 4 | ||||
-rw-r--r-- | src/core/content_client_qt.cpp | 14 | ||||
-rw-r--r-- | src/core/ozone/gl_surface_glx_qt.cpp | 2 | ||||
-rw-r--r-- | src/core/profile_io_data_qt.cpp | 169 | ||||
-rw-r--r-- | src/core/profile_io_data_qt.h | 5 | ||||
-rw-r--r-- | src/core/web_engine_context.cpp | 15 | ||||
-rw-r--r-- | src/webengine/render_widget_host_view_qt_delegate_quick.cpp | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 9 | ||||
-rw-r--r-- | src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc | 16 | ||||
-rw-r--r-- | src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc | 4 | ||||
-rw-r--r-- | src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp | 1 | ||||
-rw-r--r-- | tests/auto/widgets/origins/tst_origins.cpp | 5 | ||||
-rw-r--r-- | tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp | 16 | ||||
-rw-r--r-- | tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 23 |
16 files changed, 284 insertions, 112 deletions
diff --git a/dist/changes-5.12.1 b/dist/changes-5.12.1 new file mode 100644 index 000000000..44dfdd5c7 --- /dev/null +++ b/dist/changes-5.12.1 @@ -0,0 +1,78 @@ +Qt 5.12.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.12.1 Changes * +**************************************************************************** + +Chromium +-------- + + - Security fixes from Chromium up to version 71.0.3578.94, including: + * CVE-2018-17480 + * CVE-2018-17481 + * CVE-2018-18335 + * CVE-2018-18336 + * CVE-2018-18337 + * CVE-2018-18338 + * CVE-2018-18339 + * CVE-2018-18340 + * CVE-2018-18341 + * CVE-2018-18342 + * CVE-2018-18343 + * CVE-2018-18345 + * CVE-2018-18347 + * CVE-2018-18349 + * CVE-2018-18350 + * CVE-2018-18355 + * CVE-2018-18356 + * CVE-2018-18357 + * CVE-2018-18358 + * CVE-2018-18359 + * Security Bug 839250 + * Security Bug 851821 + * Security Bug 869067 + * Security Bug 877843 + * Security Bug 879965 + * Security Bug 880665 + * Security Bug 882270 + * Security Bug 892643 + * Security Bug 895885 + * Security Bug 900910 + - Fixed x86-32 builds on GCC 8. + - Fixed building on ARM hosts. + + +General +------- + + * Enabled idle detection and sleep inhibition on Linux and macOS. + * [QTBUG-66262] Improved suggested file name of downloads when conflicts arise. + * [QTBUG-71322] Enabled bilinear filtering of textures in software rendering mode. + * [QTBUG-71370] Fixed autoscrolling regression. + * [QTBUG-71895] Fixed crash when calling clearHttpCache(). + * [QTBUG-72260] Fixed crash on requestInterceptor changes. + * [QTBUG-72654] Fixed Event.timeStamp being 0. + * [QTBUG-72655] Fixed some JS properties of dead key event. + + +QtQuickWebEngine +---------------- + + * [QTBUG-72299] Fixed problem with blank view after reuse. diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp index d63599163..9f7288f2d 100644 --- a/src/core/api/qwebengineurlscheme.cpp +++ b/src/core/api/qwebengineurlscheme.cpp @@ -39,7 +39,9 @@ #include "qwebengineurlscheme.h" -#include <url/url_util_qt.h> +#include "url/url_util_qt.h" + +#include <QtDebug> QT_BEGIN_NAMESPACE @@ -59,6 +61,8 @@ ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ServiceWorkersAllowed, url::CustomScheme ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ViewSourceAllowed, url::CustomScheme::ViewSourceAllowed) ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ContentSecurityPolicyIgnored, url::CustomScheme::ContentSecurityPolicyIgnored) +static bool g_schemesLocked = false; + class QWebEngineUrlSchemePrivate : public QSharedData , public url::CustomScheme { @@ -357,6 +361,28 @@ void QWebEngineUrlScheme::setFlags(Flags newValue) */ void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme) { + if (scheme.d->name.empty()) { + qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty"; + return; + } + + bool needsPort = scheme.d->has_port_component(); + bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED; + if (needsPort && !hasPort) { + qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port"; + return; + } + + if (url::CustomScheme::FindScheme(scheme.d->name)) { + qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered"; + return; + } + + if (g_schemesLocked) { + qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name(); + return; + } + url::CustomScheme::AddScheme(*scheme.d); } @@ -374,4 +400,9 @@ QWebEngineUrlScheme QWebEngineUrlScheme::schemeByName(const QByteArray &name) return QWebEngineUrlScheme(); } +void QWebEngineUrlScheme::lockSchemes() +{ + g_schemesLocked = true; +} + QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlscheme.h b/src/core/api/qwebengineurlscheme.h index 88a8f5065..da3010335 100644 --- a/src/core/api/qwebengineurlscheme.h +++ b/src/core/api/qwebengineurlscheme.h @@ -46,6 +46,8 @@ #include <QtCore/qobjectdefs.h> #include <QtCore/qshareddata.h> +namespace QtWebEngineCore { class WebEngineContext; } + QT_BEGIN_NAMESPACE class QWebEngineUrlSchemePrivate; @@ -106,6 +108,8 @@ public: static QWebEngineUrlScheme schemeByName(const QByteArray &name); private: + friend QtWebEngineCore::WebEngineContext; + static void lockSchemes(); QWebEngineUrlScheme(QWebEngineUrlSchemePrivate *d); QSharedDataPointer<QWebEngineUrlSchemePrivate> d; }; diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 9065174b8..9bfc8eede 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -288,9 +288,19 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) - QDir potentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); + QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Versions"); if (potentialWidevineDir.exists()) { - QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, + QDir::Name | QDir::Reversed); + const QString library = QLatin1String("/Google Chrome Framework.framework/Versions/A/Libraries/" + "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"); + for (const QFileInfo &info : widevineVersionDirs) + pluginPaths << info.absoluteFilePath() + library; + } + + QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); + if (oldPotentialWidevineDir.exists()) { + QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName); diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp index eebefa59b..4faa08091 100644 --- a/src/core/ozone/gl_surface_glx_qt.cpp +++ b/src/core/ozone/gl_surface_glx_qt.cpp @@ -173,7 +173,7 @@ bool GLSurfaceGLXQt::Initialize(GLSurfaceFormat format) GLX_PBUFFER_HEIGHT, m_size.height(), GLX_LARGEST_PBUFFER, x11::False, GLX_PRESERVED_CONTENTS, x11::False, - GLX_NONE + NULL }; m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes); diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index e44354029..01a4e98aa 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -189,6 +189,9 @@ ProfileIODataQt::~ProfileIODataQt() #endif } + if (m_urlRequestContext && m_urlRequestContext->proxy_resolution_service()) + m_urlRequestContext->proxy_resolution_service()->OnShutdown(); + m_resourceContext.reset(); if (m_cookieDelegate) m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted @@ -240,10 +243,10 @@ void ProfileIODataQt::initializeOnIOThread() // this binds factory to io thread m_weakPtr = m_weakPtrFactory.GetWeakPtr(); QMutexLocker lock(&m_mutex); - m_initialized = true; generateAllStorage(); generateJobFactory(); setGlobalCertificateVerification(); + m_initialized = true; } void ProfileIODataQt::initializeOnUIThread() @@ -258,6 +261,7 @@ void ProfileIODataQt::initializeOnUIThread() protocolHandlerRegistry->CreateJobInterceptorFactory(); m_cookieDelegate = new CookieMonsterDelegateQt(); m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore()); + createProxyConfig(); } void ProfileIODataQt::cancelAllUrlRequests() @@ -293,11 +297,12 @@ void ProfileIODataQt::generateStorage() // We must stop all requests before deleting their backends. if (m_storage) { - m_cookieDelegate->setCookieMonster(0); - m_storage->set_cookie_store(0); + m_urlRequestContext->proxy_resolution_service()->OnShutdown(); + m_cookieDelegate->setCookieMonster(nullptr); + m_storage->set_cookie_store(nullptr); cancelAllUrlRequests(); // we need to get rid of dangling pointer due to coming storage deletion - m_urlRequestContext->set_http_transaction_factory(0); + m_urlRequestContext->set_http_transaction_factory(nullptr); m_httpNetworkSession.reset(); m_transportSecurityPersister.reset(); } @@ -317,29 +322,23 @@ void ProfileIODataQt::generateStorage() m_storage->set_cert_verifier(std::move(cert_verifier)); std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); -// FIXME: -// ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); + std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs; + for (const auto &ct_log : certificate_transparency::GetKnownLogs()) { + scoped_refptr<const net::CTLogVerifier> log_verifier = + net::CTLogVerifier::Create(std::string(ct_log.log_key, ct_log.log_key_length), + ct_log.log_name, + ct_log.log_dns_domain); + if (!log_verifier) + continue; + ct_logs.push_back(std::move(log_verifier)); + } + ct_verifier->AddLogs(ct_logs); m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer())); - - std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); - - // The System Proxy Resolver has issues on Windows with unconfigured network cards, - // which is why we want to use the v8 one - if (!m_dhcpPacFileFetcherFactory) - m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory); - - proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); - m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory( - std::move(proxyResolver), - std::unique_ptr<net::ProxyConfigService>(proxyConfigService), - net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()), - m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()), - host_resolver.get(), - nullptr /* NetLog */, - m_networkDelegate.get())); - + m_storage->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>()); + m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( + m_urlRequestContext->host_resolver())); m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>()); if (!m_dataPath.isEmpty()) { @@ -355,20 +354,23 @@ void ProfileIODataQt::generateStorage() background_task_runner); }; - if (!m_httpAuthPreferences) - m_httpAuthPreferences.reset(new net::HttpAuthPreferences()); - - m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( - host_resolver.get(), - m_httpAuthPreferences.get() -#if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) - , std::string() /* gssapi library name */ -#endif - )); m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>( new net::HttpServerPropertiesImpl)); - // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. - m_storage->set_host_resolver(std::move(host_resolver)); + + // The System Proxy Resolver has issues on Windows with unconfigured network cards, + // which is why we want to use the v8 one + if (!m_dhcpPacFileFetcherFactory) + m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory); + + proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); + m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory( + std::move(proxyResolver), + std::unique_ptr<net::ProxyConfigService>(proxyConfigService), + net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()), + m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()), + m_urlRequestContext->host_resolver(), + nullptr /* NetLog */, + m_urlRequestContext->network_delegate())); } @@ -376,10 +378,8 @@ void ProfileIODataQt::generateCookieStore() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); QMutexLocker lock(&m_mutex); - m_updateCookieStore = false; scoped_refptr<net::SQLiteChannelIDStore> channel_id_db; if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies) { @@ -393,11 +393,6 @@ void ProfileIODataQt::generateCookieStore() base::WrapUnique(new net::ChannelIDService( new net::DefaultChannelIDStore(channel_id_db.get())))); - // Unset it first to get a chance to destroy and flush the old cookie store before - // opening a new on possibly the same file. - m_cookieDelegate->setCookieMonster(0); - m_storage->set_cookie_store(0); - std::unique_ptr<net::CookieStore> cookieStore; switch (m_persistentCookiesPolicy) { case ProfileAdapter::NoPersistentCookies: @@ -437,11 +432,6 @@ void ProfileIODataQt::generateCookieStore() const std::vector<std::string> cookieableSchemes(kCookieableSchemes, kCookieableSchemes + arraysize(kCookieableSchemes)); cookieMonster->SetCookieableSchemes(cookieableSchemes); - - if (!m_updateAllStorage && m_updateHttpCache) { - // HttpCache needs to be regenerated when we generate a new channel id service - generateHttpCache(); - } } void ProfileIODataQt::generateUserAgent() @@ -451,8 +441,6 @@ void ProfileIODataQt::generateUserAgent() Q_ASSERT(m_storage); QMutexLocker lock(&m_mutex); - m_updateUserAgent = false; - m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString()))); @@ -465,10 +453,6 @@ void ProfileIODataQt::generateHttpCache() Q_ASSERT(m_storage); QMutexLocker lock(&m_mutex); - m_updateHttpCache = false; - - if (m_updateCookieStore) - generateCookieStore(); net::HttpCache::DefaultBackend* main_backend = 0; switch (m_httpCacheType) { @@ -635,6 +619,38 @@ void ProfileIODataQt::setFullConfiguration() m_dataPath = m_profileAdapter->dataPath(); } +void ProfileIODataQt::requestStorageGeneration() { + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + if (m_initialized && !m_updateAllStorage) { + m_updateAllStorage = true; + createProxyConfig(); + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr)); + } +} + +// TODO(miklocek): mojofy ProxyConfigServiceQt +void ProfileIODataQt::createProxyConfig() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). + Q_ASSERT(m_proxyConfigService == 0); + net::ProxyConfigWithAnnotation initialConfig; + ProxyPrefs::ConfigState initialConfigState = PrefProxyConfigTrackerImpl::ReadPrefConfig( + m_profileAdapter->profile()->GetPrefs(), &initialConfig); + m_proxyConfigService = + new ProxyConfigServiceQt( + net::ProxyResolutionService::CreateSystemProxyConfigService( + base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})), + initialConfig, initialConfigState); + //pass interface to io thread + m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface(); +} + void ProfileIODataQt::updateStorageSettings() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); @@ -647,28 +663,7 @@ void ProfileIODataQt::updateStorageSettings() file::ForgetServiceUserIdUserDirAssociation(userId); file::AssociateServiceUserIdWithUserDir(userId, toFilePath(m_profileAdapter->dataPath())); } - - if (!m_updateAllStorage) { - m_updateAllStorage = true; - // We must create the proxy config service on the UI loop on Linux because it - // must synchronously run on the glib message loop. This will be passed to - // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). - Q_ASSERT(m_proxyConfigService == 0); - net::ProxyConfigWithAnnotation initialConfig; - ProxyPrefs::ConfigState initialConfigState = PrefProxyConfigTrackerImpl::ReadPrefConfig( - m_profileAdapter->profile()->GetPrefs(), &initialConfig); - - m_proxyConfigService = - new ProxyConfigServiceQt( - net::ProxyResolutionService::CreateSystemProxyConfigService( - base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})), - initialConfig, initialConfigState); - //pass interface to io thread - m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface(); - if (m_initialized) - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr)); - } + requestStorageGeneration(); } void ProfileIODataQt::updateCookieStore() @@ -678,13 +673,7 @@ void ProfileIODataQt::updateCookieStore() m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); m_cookiesPath = m_profileAdapter->cookiesPath(); m_channelIdPath = m_profileAdapter->channelIdPath(); - - if (m_initialized && !m_updateAllStorage && !m_updateCookieStore) { - m_updateCookieStore = true; - m_updateHttpCache = true; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::generateCookieStore, m_weakPtr)); - } + requestStorageGeneration(); } void ProfileIODataQt::updateUserAgent() @@ -693,12 +682,7 @@ void ProfileIODataQt::updateUserAgent() QMutexLocker lock(&m_mutex); m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); m_httpUserAgent = m_profileAdapter->httpUserAgent(); - - if (m_initialized && !m_updateAllStorage && !m_updateUserAgent) { - m_updateUserAgent = true; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::generateUserAgent, m_weakPtr)); - } + requestStorageGeneration(); } void ProfileIODataQt::updateHttpCache() @@ -717,12 +701,7 @@ void ProfileIODataQt::updateHttpCache() content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); } - - if (m_initialized && !m_updateAllStorage && !m_updateHttpCache) { - m_updateHttpCache = true; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::generateHttpCache, m_weakPtr)); - } + requestStorageGeneration(); } void ProfileIODataQt::updateJobFactory() diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h index 4694ae350..b983b3a99 100644 --- a/src/core/profile_io_data_qt.h +++ b/src/core/profile_io_data_qt.h @@ -118,6 +118,8 @@ public: void updateHttpCache(); // runs on ui thread void updateJobFactory(); // runs on ui thread void updateRequestInterceptor(); // runs on ui thread + void requestStorageGeneration(); //runs on ui thread + void createProxyConfig(); //runs on ui thread void updateUsedForGlobalCertificateVerification(); // runs on ui thread bool hasPageInterceptors(); @@ -157,10 +159,7 @@ private: int m_httpCacheMaxSize = 0; bool m_initialized = false; bool m_updateAllStorage = false; - bool m_updateCookieStore = false; - bool m_updateHttpCache = false; bool m_updateJobFactory = false; - bool m_updateUserAgent = false; bool m_ignoreCertificateErrors = false; bool m_useForGlobalCertificateVerification = false; bool m_hasPageInterceptors = false; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 63a1637fe..67639dc4f 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -368,11 +368,16 @@ WebEngineContext::WebEngineContext() qputenv("force_s3tc_enable", "true"); #endif - QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc")); - qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme - | QWebEngineUrlScheme::LocalAccessAllowed - | QWebEngineUrlScheme::ViewSourceAllowed); - QWebEngineUrlScheme::registerScheme(qrcScheme); + if (QWebEngineUrlScheme::schemeByName(QByteArrayLiteral("qrc")) == QWebEngineUrlScheme()) { + // User might have registered "qrc" already with different options. + QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc")); + qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme + | QWebEngineUrlScheme::LocalAccessAllowed + | QWebEngineUrlScheme::ViewSourceAllowed); + QWebEngineUrlScheme::registerScheme(qrcScheme); + } + + QWebEngineUrlScheme::lockSchemes(); // Allow us to inject javascript like any webview toolkit. content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView(); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index ba7e99c47..e756ee157 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -63,7 +63,7 @@ RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderW setFocus(true); setActiveFocusOnTab(true); -#ifdef Q_OS_OSX +#if defined(Q_OS_MACOS) && !defined(QT_NO_OPENGL) // Check that the default QSurfaceFormat OpenGL profile is compatible with the global OpenGL // shared context profile, otherwise this could lead to a nasty crash. QOpenGLContext *globalSharedContext = QOpenGLContext::globalShareContext(); diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 790d802f0..a1ddf88d7 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -2382,6 +2382,10 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page The \a resultCallback must take a const reference to a QByteArray as parameter. If printing was successful, this byte array will contain the PDF data, otherwise, the byte array will be empty. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + \since 5.7 */ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout) @@ -2414,6 +2418,11 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res The \a resultCallback must take a boolean as parameter. If printing was successful, this boolean will have the value \c true, otherwise, its value will be \c false. + + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + \since 5.8 */ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback) diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 427668a11..877bf7175 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -487,6 +487,10 @@ The \a resultCallback must take a boolean parameter. It will be called with a value of \c true if the \a subString was found; otherwise the callback value will be \c false. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + For example: \snippet qtwebengine_qwebenginepage_snippet.cpp 0 */ @@ -615,6 +619,10 @@ \note \a resultCallback can be any of a function pointer, a functor or a lambda, and it is expected to take a QString parameter. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + \sa setHtml(), toPlainText() */ @@ -626,6 +634,10 @@ \note \a resultCallback can be any of a function pointer, a functor or a lambda, and it is expected to take a QString parameter. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + \sa toHtml() */ @@ -745,6 +757,10 @@ \warning Do not execute lengthy routines in the callback function, because it might block the rendering of the web engine page. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + See scripts() for an alternative API to inject scripts. \sa QWebEngineScript::ScriptWorldId diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 09346a446..501959ab9 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -252,6 +252,10 @@ \a resultCallback must take a boolean parameter. It will be called with a value of \c true if \a subString was found; otherwise the callback value will be \c false. + \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done + during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid + value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it. + \sa selectedText(), selectionChanged() */ diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index efdfb17d0..951360c05 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -277,6 +277,7 @@ void RenderWidgetHostViewQtDelegateWidget::show() void RenderWidgetHostViewQtDelegateWidget::hide() { m_rootItem->setVisible(false); + QQuickWidget::hide(); } bool RenderWidgetHostViewQtDelegateWidget::isVisible() const diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp index 61c7232b0..61d16bc8a 100644 --- a/tests/auto/widgets/origins/tst_origins.cpp +++ b/tests/auto/widgets/origins/tst_origins.cpp @@ -637,10 +637,7 @@ void tst_Origins::sharedWorker() QTRY_VERIFY(eval(QSL("done")).toBool()); QCOMPARE(eval(QSL("result")), QVariant(42)); - // Even unregistered schemes can create SharedWorkers. - QVERIFY(load(QSL("tst:/resources/sharedWorker.html"))); - QTRY_VERIFY(eval(QSL("done")).toBool()); - QCOMPARE(eval(QSL("result")), QVariant(42)); + // Unregistered schemes should not create SharedWorkers. QVERIFY(load(QSL("PathSyntax:/resources/sharedWorker.html"))); QTRY_VERIFY(eval(QSL("done")).toBool()); diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index bf5d320b7..b0db4e974 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -31,6 +31,7 @@ #include <QtTest/QtTest> #include <QtWebEngineCore/qwebengineurlrequestinterceptor.h> #include <QtWebEngineCore/qwebengineurlrequestjob.h> +#include <QtWebEngineCore/qwebenginecookiestore.h> #include <QtWebEngineCore/qwebengineurlschemehandler.h> #include <QtWebEngineWidgets/qwebengineprofile.h> #include <QtWebEngineWidgets/qwebenginepage.h> @@ -59,6 +60,7 @@ private Q_SLOTS: void downloadItem(); void changePersistentPath(); void initiator(); + void qtbug_72299(); // this should be the last test }; void tst_QWebEngineProfile::init() @@ -629,5 +631,19 @@ void tst_QWebEngineProfile::initiator() QCOMPARE(handler.initiator, QUrl()); } +void tst_QWebEngineProfile::qtbug_72299() +{ + QWebEngineView view; + view.setUrl(QUrl("https://www.qt.io")); + view.show(); + QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool))); + view.page()->profile()->clearHttpCache(); + view.page()->profile()->setHttpCacheType(QWebEngineProfile::NoCache); + view.page()->profile()->cookieStore()->deleteAllCookies(); + view.page()->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 1, 20000); +} + + QTEST_MAIN(tst_QWebEngineProfile) #include "tst_qwebengineprofile.moc" diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index f2810101b..17177c7fb 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -46,6 +46,7 @@ #include <QTcpSocket> #include <QStyle> #include <QtWidgets/qaction.h> +#include <QWebEngineProfile> #include <QtCore/qregularexpression.h> #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \ @@ -194,6 +195,7 @@ private Q_SLOTS: void jsKeyboardEvent(); void deletePage(); void closeOpenerTab(); + void switchPage(); }; // This will be called before the first test function is executed. @@ -3174,5 +3176,26 @@ void tst_QWebEngineView::closeOpenerTab() QVERIFY(newView->focusProxy()->isVisible()); } +void tst_QWebEngineView::switchPage() +{ + QWebEngineProfile profile; + QWebEnginePage page1(&profile); + QWebEnginePage page2(&profile); + QSignalSpy loadFinishedSpy1(&page1, SIGNAL(loadFinished(bool))); + QSignalSpy loadFinishedSpy2(&page2, SIGNAL(loadFinished(bool))); + page1.setHtml("<html><body bgcolor=\"#000000\"></body></html>"); + page2.setHtml("<html><body bgcolor=\"#ffffff\"></body></html>"); + QTRY_VERIFY(loadFinishedSpy1.count() && loadFinishedSpy2.count()); + QWebEngineView webView; + webView.resize(300,300); + webView.show(); + webView.setPage(&page1); + QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::black); + webView.setPage(&page2); + QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::white); + webView.setPage(&page1); + QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::black); +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" |