diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-06-13 10:16:32 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-06-14 10:43:10 +0200 |
commit | 939d104cc5a8208a0bef94ca14889ccd584a3526 (patch) | |
tree | 4d89c122ad5014a32cd8d4fbad6b7418944d2fb6 | |
parent | 5a7063154520544fe19bb57af3609afef898bffb (diff) | |
parent | 6c2a111f8c82b56388abf409a61a3e0d56a52156 (diff) |
Merge branch '5.7' into dev
Change-Id: I1ecb615b8df1303c27b6609970502920123b3610
61 files changed, 1459 insertions, 522 deletions
diff --git a/.qmake.conf b/.qmake.conf index ffb3dafe0..5237fb5fd 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,6 +1,5 @@ QMAKEPATH += $$PWD/tools/qmake load(qt_build_config) -CONFIG += qt_example_installs CONFIG += warning_clean MODULE_VERSION = 5.8.0 diff --git a/dist/changes-5.6.1 b/dist/changes-5.6.1 index 5a568bda9..50ab2c7fe 100644 --- a/dist/changes-5.6.1 +++ b/dist/changes-5.6.1 @@ -23,7 +23,7 @@ information about a particular change. **************************************************************************** - Chromium Snapshot: - * Security fixes from Chromium up to version 50.0.2661.94 + * Security fixes from Chromium up to version 51.0.2704.63 * [QTBUG-52602] Fixed devtools so it works with newer Chrome releases. * [QTBUG-52085, QTBUG-53108] qrc urls can now load local files. diff --git a/dist/changes-5.7.0 b/dist/changes-5.7.0 index 8b6e302b8..345a6ab9d 100644 --- a/dist/changes-5.7.0 +++ b/dist/changes-5.7.0 @@ -21,7 +21,7 @@ information about a particular change. - Chromium Snapshot: * The Chromium version has been updated to 49.0.2623.111. - * In addition security fixes from Chromium 50 have been merged. + * In addition security fixes from Chromium 50 and 51 have been merged. - Web Features: * Drag'n'drop is now supported @@ -29,6 +29,9 @@ information about a particular change. if the PPAPI Widevine CDM plugin is installed. * Spellchecking is now available if dictionaries are installed. +- OS X: + * Added 'use_appstore_compliant_code' option to allow compiling WebEngine as Mac App Store compliant. + **************************************************************************** * Qt WebEngineQML * **************************************************************************** diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp index fbee934db..14ed10dfc 100644 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp +++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp @@ -352,7 +352,6 @@ void BrowserMainWindow::setupMenu() QAction *m_find = editMenu->addAction(tr("&Find")); m_find->setShortcuts(QKeySequence::Find); connect(m_find, SIGNAL(triggered()), this, SLOT(slotEditFind())); - new QShortcut(QKeySequence(Qt::Key_Slash), this, SLOT(slotEditFind())); QAction *m_findNext = editMenu->addAction(tr("&Find Next")); m_findNext->setShortcuts(QKeySequence::FindNext); diff --git a/examples/webenginewidgets/demobrowser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp index 633b72bf1..a785ae48b 100644 --- a/examples/webenginewidgets/demobrowser/webview.cpp +++ b/examples/webenginewidgets/demobrowser/webview.cpp @@ -349,8 +349,7 @@ void WebView::setPage(WebPage *_page) connect(page(), SIGNAL(statusBarMessage(QString)), SLOT(setStatusBarText(QString))); #endif - connect(page(), SIGNAL(loadingUrl(QUrl)), - this, SIGNAL(urlChanged(QUrl))); + disconnect(page(), &QWebEnginePage::iconChanged, this, &WebView::iconChanged); connect(page(), SIGNAL(iconChanged(QIcon)), this, SLOT(onIconChanged(QIcon))); connect(page(), &WebPage::featurePermissionRequested, this, &WebView::onFeaturePermissionRequested); diff --git a/examples/webenginewidgets/demobrowser/webview.h b/examples/webenginewidgets/demobrowser/webview.h index e3df8f795..8cb502fd1 100644 --- a/examples/webenginewidgets/demobrowser/webview.h +++ b/examples/webenginewidgets/demobrowser/webview.h @@ -111,9 +111,6 @@ protected: void contextMenuEvent(QContextMenuEvent *event); void wheelEvent(QWheelEvent *event); -signals: - void iconChanged(const QIcon &icon); - private slots: void setProgress(int progress); void loadFinished(bool success); diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp index 750e7ae43..1d2796b8c 100644 --- a/examples/webenginewidgets/simplebrowser/main.cpp +++ b/examples/webenginewidgets/simplebrowser/main.cpp @@ -41,6 +41,7 @@ #include "browser.h" #include "browserwindow.h" #include <QApplication> +#include <QWebEngineSettings> QString getCommandLineUrlArgument() { @@ -59,6 +60,8 @@ int main(int argc, char **argv) QApplication app(argc, argv); app.setWindowIcon(QIcon(QLatin1String(":simplebrowser.svg"))); + QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, true); + BrowserWindow *window = new BrowserWindow(); Browser::instance().addWindow(window); diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index 9a5a75092..657993fc6 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -45,6 +45,7 @@ #include "webpopupwindow.h" #include "webview.h" #include <QContextMenuEvent> +#include <QDebug> #include <QMenu> #include <QMessageBox> #include <QTimer> diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 19b67876c..a9f5adaba 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -15,6 +15,7 @@ CONFIG -= create_prl # Copy this logic from qt_module.prf so that the intermediate library can be # created to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release contains(QT_CONFIG, build_all):CONFIG += build_all } diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index 68e1244e1..13f7220bd 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -97,7 +97,7 @@ public: BrowserContextAdapter *adapter() { return m_adapter; } #if defined(ENABLE_SPELLCHECK) - void failedToLoadDictionary(const std::string& language) override; + void failedToLoadDictionary(const std::string& language); void setSpellCheckLanguage(const QString &language); QString spellCheckLanguage() const; void setSpellCheckEnabled(bool enabled); diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index bd62f4872..712ff5703 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -56,6 +56,13 @@ namespace QtWebEngineCore { +static void registerMetaTypes() +{ + qRegisterMetaType<QClipboard::Mode>("QClipboard::Mode"); +} + +Q_CONSTRUCTOR_FUNCTION(registerMetaTypes) + Q_GLOBAL_STATIC(ClipboardChangeObserver, clipboardChangeObserver) ClipboardChangeObserver::ClipboardChangeObserver() diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index a78082581..de0fbbc6b 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -6,5 +6,9 @@ GYP_CONFIG += \ desktop_linux=1 \ enable_widevine=1 -linux-clang: GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=/usr -else: GYP_CONFIG += clang=0 host_clang=0 +clang { + GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=/usr + linux-clang-libc++: GYP_CONFIG += use_system_libcxx=1 +} else { + GYP_CONFIG += clang=0 host_clang=0 +} diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 158bb0895..49c018b23 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -57,6 +57,18 @@ #include <QLibraryInfo> #include <QString> +#if defined(Q_OS_WIN) +#include <shlobj.h> +static QString getLocalAppDataDir() +{ + QString result; + wchar_t path[MAX_PATH]; + if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE)) + result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); + return result; +} +#endif + #if defined(ENABLE_PLUGINS) // The plugin logic is based on chrome/common/chrome_content_client.cc: @@ -199,10 +211,24 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) pluginPaths << potentialWidevinePluginPath; } } +#elif defined(Q_OS_WIN) + QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"); + if (potentialWidevineDir.exists()) { + QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + for (int i = 0; i < widevineVersionDirs.size(); ++i) { + QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); +#ifdef WIN64 + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmAdapterFileName); +#else + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmAdapterFileName); #endif -#if defined(Q_OS_LINUX) + pluginPaths << potentialWidevinePluginPath; + } + } +#elif defined(Q_OS_LINUX) pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdmadapter.so") // Google Chrome - << QStringLiteral("/usr/lib/chromium/libwidevinecdmadapter.so"); // Arch + << QStringLiteral("/usr/lib/chromium/libwidevinecdmadapter.so") // Arch + << QStringLiteral("/usr/lib64/chromium/libwidevinecdmadapter.so"); // OpenSUSE style #endif } diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 3e6a9eac0..cdff4ed64 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -73,6 +73,7 @@ SOURCES = \ render_widget_host_view_qt.cpp \ renderer/content_renderer_client_qt.cpp \ renderer/pepper/pepper_flash_browser_host_qt.cpp \ + renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp \ renderer/pepper/pepper_flash_renderer_host_qt.cpp \ renderer/pepper/pepper_host_factory_qt.cpp \ renderer/pepper/pepper_isolated_file_system_message_filter.cpp \ @@ -155,6 +156,7 @@ HEADERS = \ render_widget_host_view_qt_delegate.h \ renderer/content_renderer_client_qt.h \ renderer/pepper/pepper_flash_browser_host_qt.h \ + renderer/pepper/pepper_flash_clipboard_message_filter_qt.h \ renderer/pepper/pepper_flash_renderer_host_qt.h \ renderer/pepper/pepper_host_factory_qt.h \ renderer/pepper/pepper_isolated_file_system_message_filter.h \ diff --git a/src/core/core_module.pro b/src/core/core_module.pro index fa402cc63..702b92441 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -14,6 +14,8 @@ load(qt_module) api_library_name = qtwebenginecoreapi$$qtPlatformTargetSuffix() api_library_path = $$OUT_PWD/api/$$getConfigDir() +# Do not precompile any headers. We are only interested in the linker step. +PRECOMPILED_HEADER = LIBS_PRIVATE += -L$$api_library_path CONFIG *= no_smart_library_merge diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index ef5b1d172..3982b9bd1 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -87,6 +87,7 @@ void* g_display; const char* g_extensions = NULL; +bool g_egl_surfaceless_context_supported = false; } // namespace @@ -109,6 +110,26 @@ private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceQtEGL); }; +// The following comment is cited from chromium/ui/gl/gl_surface_egl.cc: +// SurfacelessEGL is used as Offscreen surface when platform supports +// KHR_surfaceless_context and GL_OES_surfaceless_context. This would avoid the +// need to create a dummy EGLsurface in case we render to client API targets. +class GLSurfacelessQtEGL : public GLSurfaceQt { +public: + explicit GLSurfacelessQtEGL(const gfx::Size& size); + + public: + bool Initialize() Q_DECL_OVERRIDE; + void Destroy() Q_DECL_OVERRIDE; + bool IsSurfaceless() const Q_DECL_OVERRIDE; + bool Resize(const gfx::Size& size, float scale_factor, bool has_alpha) Q_DECL_OVERRIDE; + EGLSurface GetHandle() Q_DECL_OVERRIDE; + void* GetShareHandle() Q_DECL_OVERRIDE; + +private: + DISALLOW_COPY_AND_ASSIGN(GLSurfacelessQtEGL); +}; + GLSurfaceQt::~GLSurfaceQt() { @@ -342,6 +363,23 @@ bool GLSurfaceQtEGL::InitializeOneOff() return false; } + g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions, "EGL_KHR_surfaceless_context"); + if (g_egl_surfaceless_context_supported) { + scoped_refptr<GLSurface> surface = new GLSurfacelessQtEGL(Size(1, 1)); + scoped_refptr<GLContext> context = GLContext::CreateGLContext( + NULL, surface.get(), PreferIntegratedGpu); + + if (!context->MakeCurrent(surface.get())) + g_egl_surfaceless_context_supported = false; + + // Ensure context supports GL_OES_surfaceless_context. + if (g_egl_surfaceless_context_supported) { + g_egl_surfaceless_context_supported = context->HasExtension( + "GL_OES_surfaceless_context"); + context->ReleaseCurrent(surface.get()); + } + } + initialized = true; return true; } @@ -426,7 +464,7 @@ bool GLSurfaceQtEGL::Initialize() g_config, pbuffer_attributes); if (!m_surfaceBuffer) { - LOG(ERROR) << "eglCreatePbufferSurface failed with error ", GetLastEGLErrorString(); + LOG(ERROR) << "eglCreatePbufferSurface failed with error " << GetLastEGLErrorString(); Destroy(); return false; } @@ -502,6 +540,41 @@ void* GLSurfaceQt::GetConfig() return g_config; } +GLSurfacelessQtEGL::GLSurfacelessQtEGL(const gfx::Size& size) + : GLSurfaceQt(size) +{ +} + +bool GLSurfacelessQtEGL::Initialize() +{ + return true; +} + +void GLSurfacelessQtEGL::Destroy() +{ +} + +bool GLSurfacelessQtEGL::IsSurfaceless() const +{ + return true; +} + +bool GLSurfacelessQtEGL::Resize(const gfx::Size& size, float scale_factor, bool has_alpha) +{ + m_size = size; + return true; +} + +EGLSurface GLSurfacelessQtEGL::GetHandle() +{ + return EGL_NO_SURFACE; +} + +void* GLSurfacelessQtEGL::GetShareHandle() +{ + return NULL; +} + // static scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) @@ -525,7 +598,12 @@ GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) #endif } case kGLImplementationEGLGLES2: { - scoped_refptr<GLSurface> surface = new GLSurfaceQtEGL(size); + scoped_refptr<GLSurface> surface; + if (g_egl_surfaceless_context_supported) + surface = new GLSurfacelessQtEGL(size); + else + surface = new GLSurfaceQtEGL(size); + if (!surface->Initialize()) return NULL; return surface; diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro index 2e2422dce..35b85b4c7 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -34,6 +34,7 @@ force_debug_info { # Copy this logic from qt_module.prf so that ninja can run according # to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release contains(QT_CONFIG, build_all):CONFIG += build_all } @@ -81,6 +82,7 @@ contains(QT_ARCH, "arm") { else: GYP_CONFIG += arm_fpu=\"$$MFPU\" arm_neon=0 arm_neon_optional=0 } + contains(QMAKE_CFLAGS, "-marm"): GYP_CONFIG += arm_thumb=0 contains(QMAKE_CFLAGS, "-mthumb"): GYP_CONFIG += arm_thumb=1 } diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index cc87d8417..c07bd4b0c 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -44,11 +44,13 @@ #include "type_conversion.h" #include <QtCore/QCoreApplication> +#include <QtCore/QMetaObject> #include <QtCore/QThread> #include <QtPositioning/QGeoPositionInfoSource> -#include "base/message_loop/message_loop.h" #include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" #include "content/browser/geolocation/geolocation_provider_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/geolocation_provider.h" @@ -63,9 +65,9 @@ public: QtPositioningHelper(LocationProviderQt *provider); ~QtPositioningHelper(); - void start(bool highAccuracy); - void stop(); - void refresh(); + Q_INVOKABLE void start(bool highAccuracy); + Q_INVOKABLE void stop(); + Q_INVOKABLE void refresh(); private Q_SLOTS: void updatePosition(const QGeoPositionInfo &); @@ -75,6 +77,7 @@ private Q_SLOTS: private: LocationProviderQt *m_locationProvider; QGeoPositionInfoSource *m_positionInfoSource; + base::WeakPtrFactory<LocationProviderQt> m_locationProviderFactory; void postToLocationProvider(const base::Closure &task); friend class LocationProviderQt; @@ -83,14 +86,13 @@ private: QtPositioningHelper::QtPositioningHelper(LocationProviderQt *provider) : m_locationProvider(provider) , m_positionInfoSource(0) + , m_locationProviderFactory(provider) { Q_ASSERT(provider); } QtPositioningHelper::~QtPositioningHelper() { - if (m_locationProvider) - m_locationProvider->m_positioningHelper = 0; } static bool isHighAccuracySource(const QGeoPositionInfoSource *source) @@ -186,7 +188,8 @@ void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos) newPos.speed = pos.hasAttribute(QGeoPositionInfo::GroundSpeed) ? pos.attribute(QGeoPositionInfo::GroundSpeed) : -1; newPos.heading = pos.hasAttribute(QGeoPositionInfo::Direction) ? pos.attribute(QGeoPositionInfo::Direction) : -1; - postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); + if (m_locationProvider) + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); } void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) @@ -203,7 +206,8 @@ void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) newPos.error_code = content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; break; } - postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); + if (m_locationProvider) + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); } void QtPositioningHelper::timeout() @@ -213,7 +217,8 @@ void QtPositioningHelper::timeout() // argument used in JS never comes all the way to the browser process. // Let's just treat it like any other error where the position is unavailable. newPos.error_code = content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; - postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); + if (m_locationProvider) + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); } inline void QtPositioningHelper::postToLocationProvider(const base::Closure &task) @@ -230,6 +235,7 @@ LocationProviderQt::~LocationProviderQt() { if (m_positioningHelper) { m_positioningHelper->m_locationProvider = 0; + m_positioningHelper->m_locationProviderFactory.InvalidateWeakPtrs(); m_positioningHelper->deleteLater(); } } @@ -241,23 +247,21 @@ bool LocationProviderQt::StartProvider(bool highAccuracy) m_positioningHelper = new QtPositioningHelper(this); m_positioningHelper->moveToThread(guiThread); } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&QtPositioningHelper::start - , base::Unretained(m_positioningHelper), highAccuracy)); + + QMetaObject::invokeMethod(m_positioningHelper, "start", Qt::QueuedConnection, Q_ARG(bool, highAccuracy)); return true; } void LocationProviderQt::StopProvider() { if (m_positioningHelper) - BrowserThread::PostTask(BrowserThread::UI,FROM_HERE, base::Bind(&QtPositioningHelper::stop - , base::Unretained(m_positioningHelper))); + QMetaObject::invokeMethod(m_positioningHelper, "stop", Qt::QueuedConnection); } void LocationProviderQt::RequestRefresh() { if (m_positioningHelper) - BrowserThread::PostTask(BrowserThread::UI,FROM_HERE, base::Bind(&QtPositioningHelper::refresh - , base::Unretained(m_positioningHelper))); + QMetaObject::invokeMethod(m_positioningHelper, "refresh", Qt::QueuedConnection); } void LocationProviderQt::OnPermissionGranted() diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 34782b8c2..d6f88f74f 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -830,12 +830,12 @@ void RenderWidgetHostViewQt::sendDelegatedFrameAck() void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) { - if (!m_gestureProvider.OnTouchEvent(motionEvent).succeeded) + auto result = m_gestureProvider.OnTouchEvent(motionEvent); + if (!result.succeeded) return; - bool causesScrollingIfUncancelled = true; blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, - causesScrollingIfUncancelled); + result.moved_beyond_slop_region); m_host->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); } diff --git a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp new file mode 100644 index 000000000..3202548ae --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp @@ -0,0 +1,401 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// based on chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pepper_flash_clipboard_message_filter_qt.h" + +#include "base/pickle.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_thread.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_macros.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/private/ppb_flash_clipboard.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ui/base/clipboard/scoped_clipboard_writer.h" + +using content::BrowserThread; + +namespace QtWebEngineCore { + +namespace { + +const size_t kMaxClipboardWriteSize = 1000000; + +ui::ClipboardType ConvertClipboardType(uint32_t type) +{ + switch (type) { + case PP_FLASH_CLIPBOARD_TYPE_STANDARD: + return ui::CLIPBOARD_TYPE_COPY_PASTE; + case PP_FLASH_CLIPBOARD_TYPE_SELECTION: + return ui::CLIPBOARD_TYPE_SELECTION; + } + NOTREACHED(); + return ui::CLIPBOARD_TYPE_COPY_PASTE; +} + +// Functions to pack/unpack custom data from a pickle. See the header file for +// more detail on custom formats in Pepper. +// TODO(raymes): Currently pepper custom formats are stored in their own +// native format type. However we should be able to store them in the same way +// as "Web Custom" formats are. This would allow clipboard data to be shared +// between pepper applications and web applications. However currently web apps +// assume all data that is placed on the clipboard is UTF16 and pepper allows +// arbitrary data so this change would require some reworking of the chrome +// clipboard interface for custom data. +bool JumpToFormatInPickle(const base::string16& format, base::PickleIterator* iter) +{ + uint32_t size = 0; + if (!iter->ReadUInt32(&size)) + return false; + for (uint32_t i = 0; i < size; ++i) { + base::string16 stored_format; + if (!iter->ReadString16(&stored_format)) + return false; + if (stored_format == format) + return true; + int skip_length; + if (!iter->ReadLength(&skip_length)) + return false; + if (!iter->SkipBytes(skip_length)) + return false; + } + return false; +} + +bool IsFormatAvailableInPickle(const base::string16& format, const base::Pickle& pickle) +{ + base::PickleIterator iter(pickle); + return JumpToFormatInPickle(format, &iter); +} + +std::string ReadDataFromPickle(const base::string16& format, const base::Pickle& pickle) +{ + std::string result; + base::PickleIterator iter(pickle); + if (!JumpToFormatInPickle(format, &iter) || !iter.ReadString(&result)) + return std::string(); + return result; +} + +bool WriteDataToPickle(const std::map<base::string16, std::string>& data, base::Pickle* pickle) +{ + pickle->WriteUInt32(data.size()); + for (std::map<base::string16, std::string>::const_iterator it = data.begin(); it != data.end(); ++it) { + if (!pickle->WriteString16(it->first)) + return false; + if (!pickle->WriteString(it->second)) + return false; + } + return true; +} + +} // namespace + +PepperFlashClipboardMessageFilter::PepperFlashClipboardMessageFilter() {} + +PepperFlashClipboardMessageFilter::~PepperFlashClipboardMessageFilter() {} + +scoped_refptr<base::TaskRunner> +PepperFlashClipboardMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message& msg) +{ + // Clipboard writes should always occur on the UI thread due to the + // restrictions of various platform APIs. In general, the clipboard is not + // thread-safe, so all clipboard calls should be serviced from the UI thread. + if (msg.type() == PpapiHostMsg_FlashClipboard_WriteData::ID) + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); + + // Windows needs clipboard reads to be serviced from the IO thread because + // these are sync IPCs which can result in deadlocks with plugins if serviced + // from the UI thread. Note that Windows clipboard calls ARE thread-safe so it + // is ok for reads and writes to be serviced from different threads. +#if !defined(OS_WIN) + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); +#else + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); +#endif +} + +int32_t PepperFlashClipboardMessageFilter::OnResourceMessageReceived(const IPC::Message& msg, + ppapi::host::HostMessageContext* context) +{ + PPAPI_BEGIN_MESSAGE_MAP(PepperFlashClipboardMessageFilter, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_RegisterCustomFormat, + OnMsgRegisterCustomFormat) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_IsFormatAvailable, + OnMsgIsFormatAvailable) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_ReadData, + OnMsgReadData) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_WriteData, + OnMsgWriteData) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_GetSequenceNumber, + OnMsgGetSequenceNumber) + PPAPI_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +int32_t PepperFlashClipboardMessageFilter::OnMsgRegisterCustomFormat( + ppapi::host::HostMessageContext* host_context, + const std::string& format_name) +{ + uint32_t format = m_custom_formats.RegisterFormat(format_name); + if (format == PP_FLASH_CLIPBOARD_FORMAT_INVALID) + return PP_ERROR_FAILED; + host_context->reply_msg = PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply(format); + return PP_OK; +} + +int32_t PepperFlashClipboardMessageFilter::OnMsgIsFormatAvailable( + ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type, + uint32_t format) +{ + if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) { + NOTIMPLEMENTED(); + return PP_ERROR_FAILED; + } + + ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); + ui::ClipboardType type = ConvertClipboardType(clipboard_type); + bool available = false; + switch (format) { + case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: { + bool plain = clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), type); + bool plainw = clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), type); + available = plain || plainw; + break; + } + case PP_FLASH_CLIPBOARD_FORMAT_HTML: + available = clipboard->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(), type); + break; + case PP_FLASH_CLIPBOARD_FORMAT_RTF: + available = clipboard->IsFormatAvailable(ui::Clipboard::GetRtfFormatType(), type); + break; + case PP_FLASH_CLIPBOARD_FORMAT_INVALID: + break; + default: + if (m_custom_formats.IsFormatRegistered(format)) { + std::string format_name = m_custom_formats.GetFormatName(format); + std::string clipboard_data; + clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(), &clipboard_data); + base::Pickle pickle(clipboard_data.data(), clipboard_data.size()); + available = IsFormatAvailableInPickle(base::UTF8ToUTF16(format_name), pickle); + } + break; + } + + return available ? PP_OK : PP_ERROR_FAILED; +} + +int32_t PepperFlashClipboardMessageFilter::OnMsgReadData( + ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type, + uint32_t format) +{ + if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) { + NOTIMPLEMENTED(); + return PP_ERROR_FAILED; + } + + ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); + ui::ClipboardType type = ConvertClipboardType(clipboard_type); + std::string clipboard_string; + int32_t result = PP_ERROR_FAILED; + switch (format) { + case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: { + if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), type)) { + base::string16 text; + clipboard->ReadText(type, &text); + if (!text.empty()) { + result = PP_OK; + clipboard_string = base::UTF16ToUTF8(text); + break; + } + } + // If the PlainTextW format isn't available or is empty, take the + // ASCII text format. + if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), type)) { + result = PP_OK; + clipboard->ReadAsciiText(type, &clipboard_string); + } + break; + } + case PP_FLASH_CLIPBOARD_FORMAT_HTML: { + if (!clipboard->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(), type)) { + break; + } + + base::string16 html; + std::string url; + uint32_t fragment_start; + uint32_t fragment_end; + clipboard->ReadHTML(type, &html, &url, &fragment_start, &fragment_end); + result = PP_OK; + clipboard_string = base::UTF16ToUTF8(html.substr(fragment_start, fragment_end - fragment_start)); + break; + } + case PP_FLASH_CLIPBOARD_FORMAT_RTF: { + if (!clipboard->IsFormatAvailable(ui::Clipboard::GetRtfFormatType(), type)) { + break; + } + result = PP_OK; + clipboard->ReadRTF(type, &clipboard_string); + break; + } + case PP_FLASH_CLIPBOARD_FORMAT_INVALID: + break; + default: + if (m_custom_formats.IsFormatRegistered(format)) { + base::string16 format_name = + base::UTF8ToUTF16(m_custom_formats.GetFormatName(format)); + std::string clipboard_data; + clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(), + &clipboard_data); + base::Pickle pickle(clipboard_data.data(), clipboard_data.size()); + if (IsFormatAvailableInPickle(format_name, pickle)) { + result = PP_OK; + clipboard_string = ReadDataFromPickle(format_name, pickle); + } + } + break; + } + + if (result == PP_OK) { + host_context->reply_msg = PpapiPluginMsg_FlashClipboard_ReadDataReply(clipboard_string); + } + return result; +} + +int32_t PepperFlashClipboardMessageFilter::OnMsgWriteData( + ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type, + const std::vector<uint32_t>& formats, + const std::vector<std::string>& data) +{ + if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) { + NOTIMPLEMENTED(); + return PP_ERROR_FAILED; + } + if (formats.size() != data.size()) + return PP_ERROR_FAILED; + + ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); + ui::ClipboardType type = ConvertClipboardType(clipboard_type); + // If no formats are passed in clear the clipboard. + if (formats.size() == 0) { + clipboard->Clear(type); + return PP_OK; + } + + ui::ScopedClipboardWriter scw(type); + std::map<base::string16, std::string> custom_data_map; + int32_t res = PP_OK; + for (uint32_t i = 0; i < formats.size(); ++i) { + if (data[i].length() > kMaxClipboardWriteSize) { + res = PP_ERROR_NOSPACE; + break; + } + + switch (formats[i]) { + case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: + scw.WriteText(base::UTF8ToUTF16(data[i])); + break; + case PP_FLASH_CLIPBOARD_FORMAT_HTML: + scw.WriteHTML(base::UTF8ToUTF16(data[i]), std::string()); + break; + case PP_FLASH_CLIPBOARD_FORMAT_RTF: + scw.WriteRTF(data[i]); + break; + case PP_FLASH_CLIPBOARD_FORMAT_INVALID: + res = PP_ERROR_BADARGUMENT; + break; + default: + if (m_custom_formats.IsFormatRegistered(formats[i])) { + std::string format_name = m_custom_formats.GetFormatName(formats[i]); + custom_data_map[base::UTF8ToUTF16(format_name)] = data[i]; + } else { + // Invalid format. + res = PP_ERROR_BADARGUMENT; + break; + } + } + + if (res != PP_OK) + break; + } + + if (custom_data_map.size() > 0) { + base::Pickle pickle; + if (WriteDataToPickle(custom_data_map, &pickle)) { + scw.WritePickledData(pickle, ui::Clipboard::GetPepperCustomDataFormatType()); + } else { + res = PP_ERROR_BADARGUMENT; + } + } + + if (res != PP_OK) { + // Need to clear the objects so nothing is written. + scw.Reset(); + } + + return res; +} + +int32_t PepperFlashClipboardMessageFilter::OnMsgGetSequenceNumber( + ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type) +{ + if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) { + NOTIMPLEMENTED(); + return PP_ERROR_FAILED; + } + + ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); + ui::ClipboardType type = ConvertClipboardType(clipboard_type); + int64_t sequence_number = clipboard->GetSequenceNumber(type); + host_context->reply_msg = PpapiPluginMsg_FlashClipboard_GetSequenceNumberReply(sequence_number); + return PP_OK; +} + +} // namespace QtWebEngineCore diff --git a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h new file mode 100644 index 000000000..c00e668ea --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// based on chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H +#define PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "ppapi/host/resource_message_filter.h" +#include "ppapi/shared_impl/flash_clipboard_format_registry.h" + +namespace ppapi { +namespace host { +struct HostMessageContext; +} +} + +namespace ui { +class ScopedClipboardWriter; +} + +namespace QtWebEngineCore { + +// Resource message filter for accessing the clipboard in Pepper. Pepper +// supports reading/writing custom formats from the clipboard. Currently, all +// custom formats that are read/written from the clipboard through pepper are +// stored in a single real clipboard format (in the same way the "web custom" +// clipboard formats are). This is done so that we don't have to have use real +// clipboard types for each custom clipboard format which may be a limited +// resource on a particular platform. +class PepperFlashClipboardMessageFilter : public ppapi::host::ResourceMessageFilter { +public: + PepperFlashClipboardMessageFilter(); + +protected: + // ppapi::host::ResourceMessageFilter overrides. + scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(const IPC::Message& msg) override; + int32_t OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext* context) override; + +private: + ~PepperFlashClipboardMessageFilter() override; + + int32_t OnMsgRegisterCustomFormat(ppapi::host::HostMessageContext* host_context, const std::string& format_name); + int32_t OnMsgIsFormatAvailable(ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type, + uint32_t format); + int32_t OnMsgReadData(ppapi::host::HostMessageContext* host_context, + uint32_t clipoard_type, + uint32_t format); + int32_t OnMsgWriteData(ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type, + const std::vector<uint32_t>& formats, + const std::vector<std::string>& data); + int32_t OnMsgGetSequenceNumber(ppapi::host::HostMessageContext* host_context, + uint32_t clipboard_type); + + int32_t WriteClipboardDataItem(uint32_t format, + const std::string& data, + ui::ScopedClipboardWriter* scw); + + ppapi::FlashClipboardFormatRegistry m_custom_formats; + + DISALLOW_COPY_AND_ASSIGN(PepperFlashClipboardMessageFilter); +}; + +} // namespace QtWebEngineCore + +#endif // PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_host_factory_qt.cpp index a0bab1e51..9aece100c 100644 --- a/src/core/renderer/pepper/pepper_host_factory_qt.cpp +++ b/src/core/renderer/pepper/pepper_host_factory_qt.cpp @@ -54,10 +54,10 @@ #include "ppapi/shared_impl/ppapi_permissions.h" #include "pepper_flash_browser_host_qt.h" +#include "pepper_flash_clipboard_message_filter_qt.h" #include "pepper_isolated_file_system_message_filter.h" using ppapi::host::MessageFilterHost; -using ppapi::host::ResourceHost; using ppapi::host::ResourceMessageFilter; namespace QtWebEngineCore { @@ -80,10 +80,18 @@ std::unique_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHo if (!host_->IsValidInstance(instance)) return nullptr; - if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH) - && message.type() == PpapiHostMsg_Flash_Create::ID) - return base::WrapUnique( - new PepperFlashBrowserHostQt(host_, instance, resource)); + // Flash interfaces. + if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH)) { + switch (message.type()) { + case PpapiHostMsg_Flash_Create::ID: + return base::WrapUnique(new PepperFlashBrowserHostQt(host_, instance, resource)); + case PpapiHostMsg_FlashClipboard_Create::ID: { + scoped_refptr<ResourceMessageFilter> clipboard_filter(new PepperFlashClipboardMessageFilter); + return base::WrapUnique(new MessageFilterHost( + host_->GetPpapiHost(), instance, resource, clipboard_filter)); + } + } + } // Permissions for the following interfaces will be checked at the // time of the corresponding instance's methods calls (because diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 134b5b63c..15125b9d8 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -70,6 +70,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/favicon_status.h" +#include "content/public/common/content_constants.h" #include <content/public/common/drop_data.h> #include "content/public/common/page_state.h" #include "content/public/common/page_zoom.h" @@ -517,7 +518,12 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT urlString.append(","); urlString.append(encodedData.constData(), encodedData.length()); - content::NavigationController::LoadURLParams params((GURL(urlString))); + GURL dataUrlToLoad(urlString); + if (dataUrlToLoad.spec().size() > url::kMaxURLChars) { + d->adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED); + return; + } + content::NavigationController::LoadURLParams params((dataUrlToLoad)); params.load_type = content::NavigationController::LOAD_TYPE_DATA; params.base_url_for_data_url = toGurl(baseUrl); params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl); @@ -1114,10 +1120,7 @@ static blink::WebDragOperationsMask toWeb(const Qt::DropActions action) static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeData *mimeData) { - if (mimeData->hasText()) - dropData->text = toNullableString16(mimeData->text()); - if (mimeData->hasHtml()) - dropData->html = toNullableString16(mimeData->html()); + Q_ASSERT(dropData->filenames.empty()); Q_FOREACH (const QUrl &url, mimeData->urls()) { if (url.isLocalFile()) { ui::FileInfo uifi; @@ -1125,6 +1128,12 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat dropData->filenames.push_back(uifi); } } + if (!dropData->filenames.empty()) + return; + if (mimeData->hasHtml()) + dropData->html = toNullableString16(mimeData->html()); + else if (mimeData->hasText()) + dropData->text = toNullableString16(mimeData->text()); } void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos) diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 80aabaa4d..c50f38b38 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -257,6 +257,7 @@ public: virtual void updateContentsSize(const QSizeF &size) = 0; virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) = 0; + virtual bool isEnabled() const = 0; virtual QSharedPointer<BrowserContextAdapter> browserContextAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 1d39d8af8..e487fca46 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -120,6 +120,8 @@ void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const void WebContentsViewQt::Focus() { + if (!m_client->isEnabled()) + return; if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView()) rwhv->Focus(); m_client->focusContainer(); diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index 9096dd604..3fea83166 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -217,7 +217,7 @@ bool QQuickWebEngineSettings::errorPageEnabled() const Disabled by default. - \sa {Pepper Plugin API Support} + \sa {Pepper Plugin API} */ bool QQuickWebEngineSettings::pluginsEnabled() const { diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 1b1dcec25..59b5d17db 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -124,6 +124,8 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_dpiScale(1.0) , m_backgroundColor(Qt::white) , m_defaultZoomFactor(1.0) + // QTBUG-53467 + , m_menuEnabled(true) { // The gold standard for mobile web content is 160 dpi, and the devicePixelRatio expected // is the (possibly quantized) ratio of device dpi to 160 dpi. @@ -141,6 +143,8 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() // 1x, 2x, 3x etc assets that fit an integral number of pixels. setDevicePixelRatio(qMax(1, qRound(webPixelRatio))); } + if (platform == QLatin1Literal("eglfs")) + m_menuEnabled = false; #ifndef QT_NO_ACCESSIBILITY QAccessible::installFactory(&webAccessibleFactory); #endif // QT_NO_ACCESSIBILITY @@ -191,6 +195,12 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu { Q_Q(QQuickWebEngineView); + if (!m_menuEnabled) { + qWarning("You are trying to open context menu on eglfs backend, which is not currently supported\n" + "See QTBUG-53467."); + return false; + } + // Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated // on OSX. QObject *menu = ui()->addMenu(q, QString(), data.pos); @@ -1075,6 +1085,12 @@ void QQuickWebEngineViewPrivate::startDragging(const content::DropData &dropData adapter->startDragging(q_ptr->window(), dropData, allowedActions, pixmap, offset); } +bool QQuickWebEngineViewPrivate::isEnabled() const +{ + const Q_Q(QQuickWebEngineView); + return q->isEnabled(); +} + bool QQuickWebEngineView::isLoading() const { Q_D(const QQuickWebEngineView); @@ -1184,24 +1200,32 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color) The default value is false. */ -bool QQuickWebEngineView::isAudioMuted() const { +bool QQuickWebEngineView::isAudioMuted() const +{ const Q_D(QQuickWebEngineView); - return d->adapter->isAudioMuted(); - + if (d->adapter) + return d->adapter->isAudioMuted(); + return false; } -void QQuickWebEngineView::setAudioMuted(bool muted) { + +void QQuickWebEngineView::setAudioMuted(bool muted) +{ Q_D(QQuickWebEngineView); bool _isAudioMuted = isAudioMuted(); - d->adapter->setAudioMuted(muted); - if (_isAudioMuted != muted) { - Q_EMIT audioMutedChanged(muted); + if (d->adapter) { + d->adapter->setAudioMuted(muted); + if (_isAudioMuted != muted) { + Q_EMIT audioMutedChanged(muted); + } } } bool QQuickWebEngineView::recentlyAudible() const { const Q_D(QQuickWebEngineView); - return d->adapter->recentlyAudible(); + if (d->adapter) + return d->adapter->recentlyAudible(); + return false; } void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index d287b46ca..b72f79f30 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -54,6 +54,7 @@ #include <private/qtwebengineglobal_p.h> #include "qquickwebenginescript_p.h" #include <QQuickItem> +#include <QtGui/qcolor.h> QT_BEGIN_NAMESPACE diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 82a9e9612..909763614 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -187,6 +187,7 @@ public: virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; + virtual bool isEnabled() const Q_DECL_OVERRIDE; virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; @@ -233,6 +234,8 @@ private: qreal m_dpiScale; QColor m_backgroundColor; qreal m_defaultZoomFactor; + // QTBUG-53467 + bool m_menuEnabled; }; #ifndef QT_NO_ACCESSIBILITY diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf index baa4a9859..009902080 100644 --- a/src/webengine/doc/qtwebengine.qdocconf +++ b/src/webengine/doc/qtwebengine.qdocconf @@ -4,8 +4,6 @@ project = QtWebEngine description = Qt WebEngine Reference Documentation version = $QT_VERSION -examplesinstallpath = qtwebengine - qhp.projects = QtWebEngine qhp.QtWebEngine.file = qtwebengine.qhp @@ -42,8 +40,10 @@ tagfile = ../../../doc/qtwebengine/qtwebengine.tags depends += qtcore \ qtgui \ + qtlocation \ qtnetwork \ qtprintsupport \ + qtpositioning \ qtqml \ qtquick \ qtquickcontrols \ diff --git a/src/webengine/doc/src/external-resources.qdoc b/src/webengine/doc/src/external-resources.qdoc index 6356e13bb..c4cfe24af 100644 --- a/src/webengine/doc/src/external-resources.qdoc +++ b/src/webengine/doc/src/external-resources.qdoc @@ -47,7 +47,47 @@ /*! \externalpage http://www.openh264.org/ - \title OpenH264 + \title OpenH264 Project Homepage +*/ + +/*! + \externalpage http://html5demos.com/drag + \title HTML5 Demos - Drag and Drop +*/ + +/*! + \externalpage http://html5demos.com/drag-anything + \title HTML5 Demos - Simple Drag and Drop +*/ + +/*! + \externalpage http://html5demos.com/dnd-upload + \title HTML5 Demos - Drag and Drop, Automatic Upload +*/ + +/*! + \externalpage http://html5demos.com/file-api + \title HTML5 Demos - File API +*/ + +/*! + \externalpage http://www.widevine.com/wv_drm.html + \title Widevine DRM +*/ + +/*! + \externalpage http://demo.castlabs.com/ + \title castLabs +*/ + +/*! + \externalpage http://ssdemo04.swankmp.net/ + \title Swank Motion Pictures, Inc. +*/ + +/*! + \externalpage https://shaka-player-demo.appspot.com/demo/ + \title Shaka Player */ /* diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc new file mode 100644 index 000000000..52f7da928 --- /dev/null +++ b/src/webengine/doc/src/qtwebengine-features.qdoc @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtwebengine-features.html + \title Qt WebEngine Features + + \brief Summarizes Qt WebEngine features. + + Qt WebEngine supports the following Chromium features: + + \list + \li \l{Audio and Video Codecs} + \li \l{Chromium DevTools} + \li \l{Drag and Drop} + \li \l{Fullscreen} + \li \l{HTML5 DRM} + \li \l{HTML5 Geolocation} + \li \l{Pepper Plugin API} + \li \l{Print to PDF} + \li \l{WebRTC} + \endlist + + \section1 Audio and Video Codecs + + Qt WebEngine supports the MPEG-4 Part 14 (MP4) file format only if the + required proprietary audio and video codecs, such as H.264 and MPEG layer-3 + (MP3), have been enabled. Proprietary codecs can be enabled by passing the + following option to qmake when building Qt WebEngine: + + \code + qmake WEBENGINE_CONFIG+=use_proprietary_codecs + \endcode + + \warning When distributing proprietary codec libraries, you must acquire + licenses for them. + + \l FFmpeg is a cross-platform solution to record, convert, and stream audio + and video. It can be configured for use with several codecs, which rises + licensing issues during distribution with the codec libraries. For some + codecs, open source implementations, such as \l{OpenH264 Project Homepage} + {OpenH264}, are available. + + \section1 Chromium DevTools + + The Chromium DevTools provide the ability to inspect and debug layout and + performance issues of any web content. + + This feature can be tested by launching a Qt WebEngine application with the + command line option \c {--remote-debugging-port=[your-port]} or by setting + the environment variable \c QTWEBENGINE_REMOTE_DEBUGGING, and then using a + Chromium based browser (such as \l{WebEngine Demo Browser Example} + {Demo Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}) to connect + to \c {http://localhost:[your-port]}. + + For more information, see \l {Qt WebEngine Debugging and Profiling}. + + \section1 Drag and Drop + + Qt WebEngine supports HTML5 drag and drop. + + This feature can be tested by opening an HTML5 drag and drop demo, such as + \l{HTML5 Demos - Drag and Drop}, \l{HTML5 Demos - Simple Drag and Drop}, or + \l{HTML5 Demos - Drag and Drop, Automatic Upload}, in \l{WebEngine Demo + Browser Example}{Demo Browser} or \l{WebEngine Quick Nano Browser} + {Nano Browser}. + + Dragging files into the browser is not actually part of HTML5, but it is + supported. It can be tested by opening \l{HTML5 Demos - File API}. + + Support for this feature was added in Qt 5.7.0. + + \section1 Fullscreen + + Qt WebEngine supports viewing web content in fullscreen mode. For more + information, see \l{WebEngineSettings::fullscreenSupportEnabled} + {WebEngineSettings.fullscreenSupportEnabled}, + \l{WebEngineView::fullScreenRequested}{WebEngineView.fullScreenRequested}, + QWebEngineSettings::FullScreenSupportEnabled, and + QWebEnginePage::fullScreenRequested. + + This feature can be tested by playing a video from YouTube in \l{WebEngine + Demo Browser Example}{Demo Browser} or \l{WebEngine Quick Nano Browser} + {Nano Browser}, and clicking the full screen icon to go into fullscreen + mode. + + Support for this feature was added in Qt 5.6.0. + + \section1 HTML5 DRM + + Qt WebEngine supports viewing DRM protected videos if the \l{Widevine DRM} + plugin has been installed. + + The video format most commonly used by DRM services, H.264, requires + proprietary audio and video codecs. For more information about enabling the + codecs, see \l{Audio and Video Codecs}. + + This feature can be tested by playing a video in \l{WebEngine Demo Browser + Example}{Demo Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser} + from \l{castLabs}, \l{Swank Motion Pictures, Inc.}, or \l{Shaka Player}. + + Support for this feature was added in Qt 5.7.0. + + \section1 HTML5 Geolocation + + Qt WebEngine supports JavaScript Geolocation API with \l {Qt Location} as a + backend. The application has to explicitly allow the feature by using + QWebEnginePage::Geolocation or \l{WebEngineView::Feature} + {WebEngineView.Feature}. + + This feature can be tested if Qt Location has been built before Qt WebEngine. + The \c http://html5demos.com/geo page can be opened in the \l{WebEngine Demo + Browser Example}{Demo Browser} and allowed to find the current position of + the user. Note that on Windows an external GPS receiver must be connected to + the application. For more information, see \l{Qt Positioning}. + + Support for this feature was added in Qt 5.5.0. + + \section1 Pepper Plugin API + + Qt WebEngine supports loading Pepper Plugin API (PPAPI) plugins if + WebEngineSettings::pluginsEnabled or QWebEngineSettings::PluginsEnabled + is set. + + Except for the Adobe Flash Player plugin, the plugins must be loaded + manually using the Chromium command line syntax with the + \c --register-pepper-plugins argument. The argument value is a list of + entries, separated by commas, that contain the file path and one or several + MIME types, separated by semicolons: + + \code + <file-path-plugin1>;<mime-type-plugin1>,<file-path-plugin2>;<mime-type1-plugin2>;<mime-type2-plugin2> + \endcode + + For example: + + \code + --register-pepper-plugins="libppapi_example.so;application/x-ppapi-example" + \endcode + + The MIME type is important because it determines which embeds the plugin is + used for. + + Support for this feature was added in Qt 5.6.0. + + \section2 Pepper Flash Player Plugin Support + + The Pepper Flash player plugin can be loaded automatically if it is + installed in one of the following locations, depending on the platform: + + \list + \li Windows + \code + C:\Windows\SysWOW64\Macromed\Flash\pepflashplayer*.dll + C:\Windows\System32\Macromed\Flash\pepflashplayer*.dll + \endcode + \li OS X + \code + /Library/Internet Plug-Ins/PepperFlashPlayer/PepperFlashPlayer.plugin + \endcode + \li Linux + \code + /usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so + /usr/lib/PepperFlash/libpepflashplayer.so + /usr/lib64/chromium/PepperFlash/libpepflashplayer.so + \endcode + \endlist + + You can also load the Pepper Flash player from a specific location by using + command line arguments: + + \code + --ppapi-flash-path=./libpepflashplayer.so + \endcode + + By default, the Flash version is set to \c{11.2.999.999}. You can use the + \c{ppapi-flash-version=} argument to set another Flash version in the + format \c{major.minor.build.revision}: + + \code + --ppapi-flash-version=16.0.0.235 + \endcode + + This feature can be tested in \l{WebEngine Demo Browser Example}{Demo Browser} + or \l{WebEngine Quick Nano Browser}{Nano Browser} if the Adobe Flash PPAPI + plugin is installed and plugins are enabled in the browser. To test the + feature, the \c https://helpx.adobe.com/flash-player.html page can be opened + in the browser. + + \section1 Print to PDF + + Qt WebEngine supports printing a web page to a PDF file. For more + information, see QWebEnginePage::printToPdf() and + \l{WebEngineView::printToPdf}{WebEngineView.printToPdf}. + + This feature can be tested in \l{WebEngine Demo Browser Example} + {Demo Browser} by selecting \uicontrol File > \uicontrol {Print to PDF}. + + Support for this feature was added in Qt 5.7.0. + + \section1 WebRTC + + WebRTC provides browsers with Real-Time Communications (RTC) capabilities + via simple APIs. For more information, see \l{WebEngineView::Feature} + {WebEngineView.Feature} and QWebEnginePage::Feature. + + This feature can be tested by setting up a webcam or microphone and then + opening \c https://test.webrtc.org/ in \l{WebEngine Widgets Simple Browser + Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}. +*/ diff --git a/src/webengine/doc/src/qtwebengine-index.qdoc b/src/webengine/doc/src/qtwebengine-index.qdoc index 4cca431f0..e7314fcf9 100644 --- a/src/webengine/doc/src/qtwebengine-index.qdoc +++ b/src/webengine/doc/src/qtwebengine-index.qdoc @@ -46,6 +46,7 @@ \list \li \l{Qt WebEngine Overview} + \li \l{Qt WebEngine Features} \li \l{Qt WebEngine Platform Notes} \li \l{Qt WebEngine Licensing} \li \l{Qt WebEngine Debugging and Profiling} diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc index d4d9af199..7ae3afaf4 100644 --- a/src/webengine/doc/src/qtwebengine-overview.qdoc +++ b/src/webengine/doc/src/qtwebengine-overview.qdoc @@ -60,16 +60,16 @@ The functionality in Qt WebEngine is divided into the following modules: \list - \li \l{Qt WebEngine Widgets} for creating widget-based web applications - \li \l{Qt WebEngine} for creating Qt Quick based web applications - \li \l{Qt WebEngine Core} for interacting with Chromium + \li \l{Qt WebEngine Widgets Module} for creating widget-based web applications + \li \l{Qt WebEngine Module} for creating Qt Quick based web applications + \li \l{Qt WebEngine Core Module} for interacting with Chromium \endlist Page rendering and JavaScript execution are separated from the GUI process into the Qt WebEngine Process. It is a library that must be shipped with the application if the Qt libraries are bundled into the application. - \section2 Qt WebEngine Widgets + \section2 Qt WebEngine Widgets Module \image qtwebenginewidgets-model.png @@ -82,7 +82,7 @@ \e cookies. Profiles can be used to isolate pages from each other. A typical use case is a dedicated profile for a \e {private browsing} mode, where no information is permanently saved. - \section2 Qt WebEngine + \section2 Qt WebEngine Module \image qtwebengine-model.png @@ -90,7 +90,7 @@ except that there is no separately accessible web engine page. The supported page functionality is integrated into the web engine view. - \section2 Qt WebEngine Core + \section2 Qt WebEngine Core Module The Qt WebEngine core is based on the \l {Chromium Project}. Chromium provides its own network and painting engines and is developed tightly together with its dependent modules, and diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index 4bb449016..ecec53bda 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -87,6 +87,7 @@ \section2 Linux On Linux, Clang or GCC version 4.7 or later is required. + Supported configurations are \c linux-g++ and \c{linux-clang}. Qt WebEngine requires \c pkg-config to detect most of its dependencies. The following \c pkg-config files are required: @@ -118,84 +119,6 @@ \note Qt WebEngine cannot be built for the 32-bit mode of OS X (using the \c macx-clang-32 \c mkspec). - \section1 Pepper Plugin API Support - - Qt WebEngine supports loading Pepper Plugin API (PPAPI) plugins if - WebEngineSettings::pluginsEnabled or QWebEngineSettings::PluginsEnabled - is set. - - Except for the Adobe Flash Player plugin, the plugins must be loaded manually using the - Chromium command line syntax with the \c --register-pepper-plugins argument. - The argument value is a list of entries, separated by commas, that contain the file path and - one or several MIME types, separated by semicolons: - - \code - <file-path-plugin1>;<mime-type-plugin1>,<file-path-plugin2>;<mime-type1-plugin2>;<mime-type2-plugin2> - \endcode - - For example: - - \code - --register-pepper-plugins="libppapi_example.so;application/x-ppapi-example" - \endcode - - The MIME type is important because it determines which embeds the plugin is used for. - - \section2 Pepper Flash Player Plugin Support - - The Pepper Flash player plugin can be loaded automatically if it is installed in one of the - following locations, depending on the platform: - - \list - \li Windows - \code - C:\Windows\SysWOW64\Macromed\Flash\pepflashplayer*.dll - C:\Windows\System32\Macromed\Flash\pepflashplayer*.dll - \endcode - \li OS X - \code - /Library/Internet Plug-Ins/PepperFlashPlayer/PepperFlashPlayer.plugin - \endcode - \li Linux - \code - /usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so - /usr/lib/PepperFlash/libpepflashplayer.so - /usr/lib64/chromium/PepperFlash/libpepflashplayer.so - \endcode - \endlist - - You can also load the Pepper Flash player from a specific location by using command line - arguments: - - \code - --ppapi-flash-path=./libpepflashplayer.so - \endcode - - By default, the Flash version is set to \c{11.2.999.999}. You can use the - \c{ppapi-flash-version=} argument to set another Flash version in the - in the format \c{major.minor.build.revision}: - - \code - --ppapi-flash-version=16.0.0.235 - \endcode - - \section1 Audio and Video Codec Support - - Qt WebEngine supports the MPEG-4 Part 14 (MP4) file format only if the required proprietary - audio and video codecs, such as H.264 and MPEG layer-3 (MP3), have been enabled. Proprietary - codecs can be enabled by passing the following option to qmake: - - \code - qmake WEBENGINE_CONFIG+=use_proprietary_codecs - \endcode - - \warning When distributing proprietary codec libraries, you must acquire licenses for them. - - \l FFmpeg is a cross-platform solution to record, convert, and stream audio and video. It can - be configured for use with several codecs, which rises licensing issues during distribution - with the codec libraries. For some codecs, open source implementations, such as \l {OpenH264}, - are available. - \section1 Mac App Store Compatibility By default, Qt WebEngine uses private OS X API, which might cause an application to be @@ -203,7 +126,7 @@ calls, Qt WebEngine has to be recompiled: \code - qmake WEBENGINE_CONFIG += use_appstore_compliant_code + qmake WEBENGINE_CONFIG+=use_appstore_compliant_code \endcode However, this will cause some behavioral changes, such as: diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index a4630484e..0f83d0d23 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -404,7 +404,7 @@ \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page. - To clear the selection, just pass an empty string. + To clear the search highlight, just pass an empty string. */ /*! @@ -412,7 +412,7 @@ \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page, using the given \a options. - To clear the selection, just pass an empty string. + To clear the search highlight, just pass an empty string. \code findText("Qt", WebEngineView.FindBackward | WebEngineView.FindCaseSensitively); @@ -424,7 +424,7 @@ \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page, using the given \a options. - To clear the selection, just pass an empty string. + To clear the search highlight, just pass an empty string. The \a resultCallback must take a boolean parameter. It will be called with a value of true if the \a subString was found; otherwise the callback value 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 9ad86800c..5e39cc2b3 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -222,18 +222,33 @@ void RenderWidgetHostViewQtDelegateQuick::focusOutEvent(QFocusEvent *event) void RenderWidgetHostViewQtDelegateQuick::mousePressEvent(QMouseEvent *event) { - if (!m_isPopup && (parentItem() && parentItem()->property("activeFocusOnPress").toBool())) + QQuickItem *parent = parentItem(); + if (!m_isPopup && (parent && parent->property("activeFocusOnPress").toBool())) forceActiveFocus(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::mouseMoveEvent(QMouseEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::mouseReleaseEvent(QMouseEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } @@ -254,14 +269,24 @@ void RenderWidgetHostViewQtDelegateQuick::wheelEvent(QWheelEvent *event) void RenderWidgetHostViewQtDelegateQuick::touchEvent(QTouchEvent *event) { + QQuickItem *parent = parentItem(); if (event->type() == QEvent::TouchBegin && !m_isPopup - && (parentItem() && parentItem()->property("activeFocusOnPress").toBool())) + && (parent && parent->property("activeFocusOnPress").toBool())) forceActiveFocus(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::hoverMoveEvent(QHoverEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.cpp b/src/webenginewidgets/api/qwebenginecertificateerror.cpp index ebe3cdbec..289bb7ec0 100644 --- a/src/webenginewidgets/api/qwebenginecertificateerror.cpp +++ b/src/webenginewidgets/api/qwebenginecertificateerror.cpp @@ -85,6 +85,10 @@ QWebEngineCertificateError::~QWebEngineCertificateError() This enum describes the type of certificate error encountered. + The values of this enum type match the SSL errors Chromium provides. + QSslError::SslError values are not used directly, because the Qt error + categories cannot be mapped to the Chromium error categories. + \value SslPinnedKeyNotInCertificateChain The certificate did not match the built-in public keys pinned for the host name. \value CertificateCommonNameInvalid The certificate's common name did not match the host name. diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 0e7f02f16..3f11e5aef 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -1143,6 +1143,7 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData view->contextMenuEvent(&event); break; case Qt::CustomContextMenu: + contextData = data; Q_EMIT view->customContextMenuRequested(data.pos); break; case Qt::ActionsContextMenu: @@ -1269,9 +1270,21 @@ void QWebEnginePagePrivate::startDragging(const content::DropData &dropData, adapter->startDragging(view, dropData, allowedActions, pixmap, offset); } +bool QWebEnginePagePrivate::isEnabled() const +{ + const Q_Q(QWebEnginePage); + const QWidget *view = q->view(); + if (view) + return view->isEnabled(); + return true; +} + QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); + if (!d->contextData.d) + return nullptr; + QMenu *menu = new QMenu(d->view); QAction *action = 0; const WebEngineContextMenuData &contextMenuData = *d->contextData.d; diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 22bfaff95..26ef80e9a 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -135,6 +135,7 @@ public: virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; + virtual bool isEnabled() const Q_DECL_OVERRIDE; virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc index e6236ec98..89d7cfb0c 100644 --- a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc +++ b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc @@ -248,7 +248,7 @@ \b {Qt WebEngine} \code QWebEnginePage page; - page.runJavascript("document.documentElement.contentEditable = true"); + page.runJavaScript("document.documentElement.contentEditable = true"); \endcode @@ -287,7 +287,7 @@ \li QWebPage::setContentEditable \li In the latest HTML standard, any document element can be made editable through the \c contentEditable attribute. So \c runJavaScript is all that is needed: - \c{page->runJavascript("document.documentElement.contentEditable = true")} + \c{page->runJavaScript("document.documentElement.contentEditable = true")} \row \li QWebPage::setLinkDelegationPolicy \li There is no way to connect a signal to run C++ code when a link is clicked. However, diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index fab4827a0..539e809d4 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -281,6 +281,9 @@ the user clicks on the web page with the right mouse button. It is called from the default \l{QWidget::}{contextMenuEvent()} handler. The popup menu's ownership is transferred to the caller. + + Returns \c nullptr if the context menu data is not initialized, for example when it + is called when there is actually no context menu requested. */ /*! @@ -411,14 +414,14 @@ \fn void QWebEnginePage::findText(const QString &subString, FindFlags options) Finds the specified string, \a subString, in the page, using the given \a options. - To clear the selection, just pass an empty string. + To clear the search highlight, just pass an empty string. */ /*! \fn void QWebEnginePage::findText(const QString &subString, FindFlags options, FunctorOrLambda resultCallback) Finds the specified string, \a subString, in the page, using the given \a options. - To clear the selection, just pass an empty string. + To clear the search highlight, just pass an empty string. 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. @@ -615,6 +618,10 @@ \warning This function works only for HTML, for other mime types (such as XHTML and SVG) setContent() should be used instead. + \warning The content will be percent encoded before being sent to the renderer via IPC. + This may increase its size. The maximum size of the percent encoded content is + 2 megabytes minus 30 bytes. + \sa toHtml(), setContent(), load() */ @@ -630,6 +637,10 @@ \note This method will not affect session or global history for the page. + \warning The content will be percent encoded before being sent to the renderer via IPC. + This may increase its size. The maximum size of the percent encoded content is + 2 megabytes minus 6 bytes plus the length of the mime type string. + \sa toHtml(), setHtml() */ diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index 3e0f4cf82..558aa1f50 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -88,7 +88,8 @@ This enum type specifies settings for web pages: \value AutoLoadImages - Automatically loads images on web pages. Enabled by default. + Automatically dowloads images for web pages. When this setting is + disabled, images are loaded from the cache. Enabled by default. \value JavascriptEnabled Enables the running of JavaScript programs. Enabled by default. \value JavascriptCanOpenWindows @@ -130,7 +131,7 @@ Enables displaying the built-in error pages of Chromium. Enabled by default. \value PluginsEnabled Enables support for Pepper plugins, such as the Flash player. Disabled by default. - See also \l{Pepper Plugin API Support}. (Added in Qt 5.6) + See also \l{Pepper Plugin API}. (Added in Qt 5.6) \value FullScreenSupportEnabled Enables fullscreen support in an application. Disabled by default. (Added in Qt 5.6) \value ScreenCaptureEnabled 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 3f70187e7..99621b602 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -298,6 +298,34 @@ void RenderWidgetHostViewQtDelegateWidget::hideEvent(QHideEvent *event) bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event) { bool handled = false; + + // Mimic QWidget::event() by ignoring mouse, keyboard, touch and tablet events if the widget is + // disabled. + if (!isEnabled()) { + switch (event->type()) { + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::TabletMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + case QEvent::ContextMenu: + case QEvent::KeyPress: + case QEvent::KeyRelease: +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: +#endif + return false; + default: + break; + } + } + if (event->type() == QEvent::MouseButtonDblClick) { // QWidget keeps the Qt4 behavior where the DblClick event would replace the Press event. // QtQuick is different by sending both the Press and DblClick events for the second press diff --git a/sync.profile b/sync.profile index 7d6daec35..e4a88e0c2 100644 --- a/sync.profile +++ b/sync.profile @@ -20,7 +20,7 @@ %dependencies = ( "qtbase" => "", "qtdeclarative" => "", - "qtxmlpatterns" => "", + "qtlocation" => "", "qttools" => "", # FIXME: take examples out into their own module to avoid a potential circular dependency later ? "qtquickcontrols" => "", diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 34170da8a..1937dca04 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -364,6 +364,7 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineCertificateError.CertificateNonUniqueName --> Error" << "QQuickWebEngineCertificateError.CertificateWeakKey --> Error" << "QQuickWebEngineCertificateError.CertificateNameConstraintViolation --> Error" + << "QQuickWebEngineCertificateError.CertificateValidityTooLong --> Error" << "QQuickWebEngineCertificateError.url --> QUrl" << "QQuickWebEngineCertificateError.error --> Error" << "QQuickWebEngineCertificateError.description --> QString" @@ -492,13 +493,11 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void" << "QQuickWebEngineSettings.screenCaptureEnabled --> bool" << "QQuickWebEngineSettings.webGLEnabled --> bool" - << "QQuickWebEngineSettings.webAudioEnabled --> bool" << "QQuickWebEngineSettings.accelerated2dCanvasEnabled --> bool" << "QQuickWebEngineSettings.autoLoadIconsForPage --> bool" << "QQuickWebEngineSettings.touchIconsEnabled --> bool" << "QQuickWebEngineSettings.screenCaptureEnabledChanged() --> void" << "QQuickWebEngineSettings.webGLEnabledChanged() --> void" - << "QQuickWebEngineSettings.webAudioEnabledChanged() --> void" << "QQuickWebEngineSettings.accelerated2dCanvasEnabledChanged() --> void" << "QQuickWebEngineSettings.autoLoadIconsForPageChanged() --> void" << "QQuickWebEngineSettings.touchIconsEnabledChanged() --> void" diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST index d4d5c9844..2cde59454 100644 --- a/tests/auto/quick/qquickwebengineview/BLACKLIST +++ b/tests/auto/quick/qquickwebengineview/BLACKLIST @@ -1,2 +1,5 @@ [transparentWebEngineViews] windows + +[inputEventForwardingDisabledWhenActiveFocusOnPressDisabled] +* diff --git a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro index 826b47de7..36e74a2a8 100644 --- a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro +++ b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro @@ -1,6 +1,6 @@ include(../tests.pri) exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc -QT_PRIVATE += webengine-private +QT_PRIVATE += webengine-private gui-private HEADERS += ../shared/util.h diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 0def76d6f..1c5461fa7 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -31,6 +31,7 @@ #include <QScopedPointer> #include <QtCore/qelapsedtimer.h> +#include <QtGui/qpa/qwindowsysteminterface.h> #include <QtQml/QQmlEngine> #include <QtTest/QtTest> #include <private/qquickwebengineview_p.h> @@ -71,6 +72,9 @@ private Q_SLOTS: void basicRenderingSanity(); void setZoomFactor(); void printToPdf(); + void stopSettingFocusWhenDisabled(); + void stopSettingFocusWhenDisabled_data(); + void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -514,5 +518,139 @@ void tst_QQuickWebEngineView::printToPdf() QVERIFY(!QFile::exists(path)); } +void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(bool, activeFocusResult); + + QQuickWebEngineView *view = webEngineView(); + m_window->show(); + view->setSize(QSizeF(640, 480)); + view->setEnabled(viewEnabled); + view->loadHtml("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + QVERIFY(waitForLoadSucceeded(view)); + + // When enabled, the view should get active focus after the page is loaded. + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), activeFocusResult, 1000); + view->runJavaScript("document.getElementById(\"input\").focus()"); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), activeFocusResult, 1000); +} + +void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled_data() +{ + QTest::addColumn<bool>("viewEnabled"); + QTest::addColumn<bool>("activeFocusResult"); + + QTest::newRow("enabled view gets active focus") << true << true; + QTest::newRow("disabled view does not get active focus") << false << false; +} + +class MouseTouchEventRecordingItem : public QQuickItem { +public: + explicit MouseTouchEventRecordingItem(QQuickItem *parent = 0) : + QQuickItem(parent), m_eventCounter(0) { + setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + setAcceptHoverEvents(true); + } + + bool event(QEvent *event) Q_DECL_OVERRIDE + { + switch (event->type()) { + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::TabletMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + case QEvent::HoverEnter: + case QEvent::HoverMove: + case QEvent::HoverLeave: + ++m_eventCounter; + event->accept(); + return true; + default: + break; + } + return QQuickItem::event(event); + } + + void clearEventCount() + { + m_eventCounter = 0; + } + + int eventCount() + { + return m_eventCounter; + } + +private: + int m_eventCounter; +}; + +void tst_QQuickWebEngineView::inputEventForwardingDisabledWhenActiveFocusOnPressDisabled() +{ + QQuickWebEngineView *view = webEngineView(); + MouseTouchEventRecordingItem item; + item.setParentItem(m_window->contentItem()); + item.setSize(QSizeF(640, 480)); + view->setParentItem(&item); + view->setSize(QSizeF(640, 480)); + m_window->show(); + + // Simulate click and move of mouse, so that last known position in the application + // is updated, thus a mouse move event is not generated when we don't expect it. + QTest::mouseClick(view->window(), Qt::LeftButton); + item.clearEventCount(); + + // First disable view, so it does not receive focus on page load. + view->setEnabled(false); + view->setActiveFocusOnPress(false); + view->loadHtml("<html><head>" + "<script>" + "window.onload = function() { document.getElementById(\"input\").focus(); }" + "</script>" + "<title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + QVERIFY(waitForLoadSucceeded(view)); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), false, 1000); + + // Enable the view back so we can try to interact with it. + view->setEnabled(true); + + // Click on the view, to try and set focus. + QTest::mouseClick(view->window(), Qt::LeftButton); + + // View should not have focus after click, because setActiveFocusOnPress is false. + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), false, 1000); + + // Now test sending various input events, to check that indeed all the input events are not + // forwarded to Chromium, but rather processed and accepted by the view's parent item. + QTest::mousePress(view->window(), Qt::LeftButton); + QTest::mouseRelease(view->window(), Qt::LeftButton); + + QTouchDevice *device = new QTouchDevice; + device->setType(QTouchDevice::TouchScreen); + QWindowSystemInterface::registerTouchDevice(device); + + QTest::touchEvent(view->window(), device).press(0, QPoint(0,0), view->window()); + QTest::touchEvent(view->window(), device).move(0, QPoint(1, 1), view->window()); + QTest::touchEvent(view->window(), device).release(0, QPoint(1, 1), view->window()); + + // We expect to catch 7 events - click = 2, press + release = 2, touches = 3. + QCOMPARE(item.eventCount(), 7); + + // Manually forcing focus should still be possible. + view->forceActiveFocus(); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), true, 1000); +} + QTEST_MAIN(tst_QQuickWebEngineView) #include "tst_qquickwebengineview.moc" diff --git a/tests/auto/widgets/positionplugin/plugin.cpp b/tests/auto/widgets/positionplugin/plugin.cpp deleted file mode 100644 index ca2e7eb45..000000000 --- a/tests/auto/widgets/positionplugin/plugin.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtPositioning/qgeopositioninfosource.h> -#include <QtPositioning/qgeopositioninfosourcefactory.h> -#include <QObject> -#include <QtPlugin> - -class DummySource : public QGeoPositionInfoSource -{ - Q_OBJECT - -public: - DummySource(QObject *parent=0); - - void startUpdates() {} - void stopUpdates() {} - void requestUpdate(int) {} - - QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const; - PositioningMethods supportedPositioningMethods() const; - - int minimumUpdateInterval() const; - Error error() const; -}; - -DummySource::DummySource(QObject *parent) : - QGeoPositionInfoSource(parent) -{ -} - -QGeoPositionInfoSource::Error DummySource::error() const -{ - return QGeoPositionInfoSource::NoError; -} - -int DummySource::minimumUpdateInterval() const -{ - return 1000; -} - -QGeoPositionInfo DummySource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const -{ - Q_UNUSED(fromSatellitePositioningMethodsOnly); - return QGeoPositionInfo(QGeoCoordinate(54.186824, 12.087262), QDateTime::currentDateTime()); -} - -QGeoPositionInfoSource::PositioningMethods DummySource::supportedPositioningMethods() const -{ - return QGeoPositionInfoSource::AllPositioningMethods; -} - - -class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactory -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" - FILE "plugin.json") - Q_INTERFACES(QGeoPositionInfoSourceFactory) - -public: - QGeoPositionInfoSource *positionInfoSource(QObject *parent); - QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); - QGeoAreaMonitorSource *areaMonitor(QObject *parent); -}; - -QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent) -{ - return new DummySource(parent); -} - -QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *) -{ - return 0; -} - -QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* ) -{ - return 0; -} - -#include "plugin.moc" diff --git a/tests/auto/widgets/positionplugin/plugin.json b/tests/auto/widgets/positionplugin/plugin.json deleted file mode 100644 index 68acaded3..000000000 --- a/tests/auto/widgets/positionplugin/plugin.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Keys": ["test.source"], - "Provider": "test.source", - "Position": true, - "Satellite": false, - "Monitor": false, - "Priority": 0, - "Testable": true -} diff --git a/tests/auto/widgets/positionplugin/positionplugin.pro b/tests/auto/widgets/positionplugin/positionplugin.pro deleted file mode 100644 index 6f2e736c6..000000000 --- a/tests/auto/widgets/positionplugin/positionplugin.pro +++ /dev/null @@ -1,13 +0,0 @@ -TARGET = qtwebengine_positioning_testplugin - -QT += positioning - -SOURCES += plugin.cpp - -OTHER_FILES += \ - plugin.json - -PLUGIN_TYPE = position -PLUGIN_CLASS_NAME = TestPositionPlugin -PLUGIN_EXTENDS = - -load(qt_plugin) diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index 30b43d6b7..fcd36ba83 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -1,11 +1,2 @@ -[geolocationRequestJS] -* - [macCopyUnicodeToClipboard] osx - -[getUserMediaRequest] -windows - -[setHtmlWithImageResource] -* diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 3e0a5abae..e50692226 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -201,9 +201,6 @@ private Q_SLOTS: void progressSignal(); void urlChange(); void requestedUrlAfterSetAndLoadFailures(); - void javaScriptWindowObjectCleared_data(); - void javaScriptWindowObjectCleared(); - void javaScriptWindowObjectClearedOnEvaluate(); void asyncAndDelete(); void earlyToHtml(); void setHtml(); @@ -215,7 +212,6 @@ private Q_SLOTS: void hitTestContent(); void baseUrl_data(); void baseUrl(); - void renderHints(); void scrollPosition(); void scrollToAnchor(); void scrollbarsOff(); @@ -412,16 +408,21 @@ void tst_QWebEnginePage::geolocationRequestJS() newPage, SLOT(requestPermission(const QUrl&, QWebEnginePage::Feature))); QSignalSpy spyLoadFinished(newPage, SIGNAL(loadFinished(bool))); - newPage->setHtml(QString("<html><body>test</body></html>"), QUrl()); + newPage->setHtml(QString("<html><body>test</body></html>"), QUrl("qrc://secure/origin")); QTRY_COMPARE(spyLoadFinished.count(), 1); if (evaluateJavaScriptSync(newPage, QLatin1String("!navigator.geolocation")).toBool()) { delete view; W_QSKIP("Geolocation is not supported.", SkipSingle); } - evaluateJavaScriptSync(newPage, "var errorCode = 0; function error(err) { errorCode = err.code; } function success(pos) { } navigator.geolocation.getCurrentPosition(success, error)"); + evaluateJavaScriptSync(newPage, "var errorCode = 0; var done = false; function error(err) { errorCode = err.code; done = true; } function success(pos) { done = true; } navigator.geolocation.getCurrentPosition(success, error)"); + + QTRY_VERIFY(evaluateJavaScriptSync(newPage, "done").toBool()); + int result = evaluateJavaScriptSync(newPage, "errorCode").toInt(); + if (result == 2) + QEXPECT_FAIL("", "No location service available.", Continue); + QCOMPARE(result, errorCode); - QTRY_COMPARE(evaluateJavaScriptSync(newPage, "errorCode").toInt(), errorCode); delete view; } @@ -3879,48 +3880,6 @@ void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures() QVERIFY(!spy.at(1).first().toBool()); } -void tst_QWebEnginePage::javaScriptWindowObjectCleared_data() -{ - QTest::addColumn<QString>("html"); - QTest::addColumn<int>("signalCount"); - QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1; - // NOTE: Empty scripts no longer cause this signal to be emitted. - QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0; - QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0; -} - -void tst_QWebEnginePage::javaScriptWindowObjectCleared() -{ -#if !defined(QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED) - QSKIP("QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED"); -#else - QWebEnginePage page; - QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared())); - QFETCH(QString, html); - page.setHtml(html); - - QFETCH(int, signalCount); - QCOMPARE(spy.count(), signalCount); -#endif -} - -void tst_QWebEnginePage::javaScriptWindowObjectClearedOnEvaluate() -{ -#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT) - QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT"); -#else - QWebEnginePage page; - QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared())); - page.setHtml("<html></html>"); - QCOMPARE(spy.count(), 0); - page.evaluateJavaScript("var a = 'a';"); - QCOMPARE(spy.count(), 1); - // no new clear for a new script: - page.evaluateJavaScript("var a = 1;"); - QCOMPARE(spy.count(), 1); -#endif -} - void tst_QWebEnginePage::asyncAndDelete() { QWebEnginePage *page = new QWebEnginePage; @@ -3954,28 +3913,26 @@ void tst_QWebEnginePage::setHtml() void tst_QWebEnginePage::setHtmlWithImageResource() { - // By default, only security origins of local files can load local resources. - // So we should specify baseUrl to be a local file in order to get a proper origin and load the local image. + // We allow access to qrc resources from any security origin, including local and anonymous QLatin1String html("<html><body><p>hello world</p><img src='qrc:/resources/image.png'/></body></html>"); QWebEnginePage page; - page.setHtml(html, QUrl(QLatin1String("file:///path/to/file"))); - waitForSignal(&page, SIGNAL(loadFinished(bool))); + QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); + page.setHtml(html, QUrl("file:///path/to/file")); + QTRY_COMPARE(spy.count(), 1); QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1); QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128); QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128); - // Now we test the opposite: without a baseUrl as a local file, we cannot request local resources. + // Now we test the opposite: without a baseUrl as a local file, we can still request qrc resources. page.setHtml(html); - waitForSignal(&page, SIGNAL(loadFinished(bool))); + QTRY_COMPARE(spy.count(), 2); QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1); - QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue); - QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 0); - QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue); - QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 0); + QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128); + QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128); } void tst_QWebEnginePage::setHtmlWithStylesheetResource() @@ -4154,167 +4111,30 @@ void tst_QWebEnginePage::baseUrl() QCOMPARE(baseUrlSync(m_page), baseUrl); } -class DummyPaintEngine: public QPaintEngine { -public: - - DummyPaintEngine() - : QPaintEngine(QPaintEngine::AllFeatures) - , renderHints(0) - { - } - - bool begin(QPaintDevice*) - { - setActive(true); - return true; - } - - bool end() - { - setActive(false); - return false; - } - - void updateState(const QPaintEngineState& state) - { - renderHints = state.renderHints(); - } - - void drawPath(const QPainterPath&) { } - void drawPixmap(const QRectF&, const QPixmap&, const QRectF&) { } - - QPaintEngine::Type type() const - { - return static_cast<QPaintEngine::Type>(QPaintEngine::User + 2); - } - - QPainter::RenderHints renderHints; -}; - -class DummyPaintDevice: public QPaintDevice { -public: - DummyPaintDevice() - : QPaintDevice() - , m_engine(new DummyPaintEngine) - { - } - - ~DummyPaintDevice() - { - delete m_engine; - } - - QPaintEngine* paintEngine() const - { - return m_engine; - } - - QPainter::RenderHints renderHints() const - { - return m_engine->renderHints; - } - -protected: - int metric(PaintDeviceMetric metric) const; - -private: - DummyPaintEngine* m_engine; - friend class DummyPaintEngine; -}; - - -int DummyPaintDevice::metric(PaintDeviceMetric metric) const -{ - switch (metric) { - case PdmWidth: - return 400; - break; - - case PdmHeight: - return 200; - break; - - case PdmNumColors: - return INT_MAX; - break; - - case PdmDepth: - return 32; - break; - - default: - break; - } - return 0; -} - -void tst_QWebEnginePage::renderHints() -{ -#if !defined(QWEBENGINEPAGE_RENDER) - QSKIP("QWEBENGINEPAGE_RENDER"); -#else - QString html("<html><body><p>Hello, world!</p></body></html>"); - - QWebEnginePage page; - page.setHtml(html); - page.setViewportSize(page.contentsSize()); - - // We will call frame->render and trap the paint engine state changes - // to ensure that GraphicsContext does not clobber the render hints. - DummyPaintDevice buffer; - QPainter painter(&buffer); - - painter.setRenderHint(QPainter::TextAntialiasing, false); - page.render(&painter); - QVERIFY(!(buffer.renderHints() & QPainter::TextAntialiasing)); - QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform)); - QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing)); - - painter.setRenderHint(QPainter::TextAntialiasing, true); - page.render(&painter); - QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing); - QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform)); - QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing)); - - painter.setRenderHint(QPainter::SmoothPixmapTransform, true); - page.render(&painter); - QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing); - QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform); - QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing)); - - painter.setRenderHint(QPainter::HighQualityAntialiasing, true); - page.render(&painter); - QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing); - QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform); - QVERIFY(buffer.renderHints() & QPainter::HighQualityAntialiasing); -#endif -} - void tst_QWebEnginePage::scrollPosition() { -#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT) - QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT"); -#else // enlarged image in a small viewport, to provoke the scrollbars to appear QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>"); - QWebEnginePage page; - page.setViewportSize(QSize(200, 200)); + QWebEngineView view; + view.setFixedSize(200,200); + view.show(); - page.setHtml(html); - page.setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); - page.setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + QTest::qWaitForWindowExposed(&view); + + QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool))); + view.setHtml(html); + QTRY_COMPARE(loadSpy.count(), 1); // try to set the scroll offset programmatically - page.setScrollPosition(QPoint(23, 29)); - QCOMPARE(page.scrollPosition().x(), 23); - QCOMPARE(page.scrollPosition().y(), 29); + view.page()->runJavaScript("window.scrollTo(23, 29);"); + QTRY_COMPARE(view.page()->scrollPosition().x(), qreal(23)); + QCOMPARE(view.page()->scrollPosition().y(), qreal(29)); - int x = page.evaluateJavaScript("window.scrollX").toInt(); - int y = page.evaluateJavaScript("window.scrollY").toInt(); + int x = evaluateJavaScriptSync(view.page(), "window.scrollX").toInt(); + int y = evaluateJavaScriptSync(view.page(), "window.scrollY").toInt(); QCOMPARE(x, 23); QCOMPARE(y, 29); -#endif } void tst_QWebEnginePage::scrollToAnchor() diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 8aaf9ccc3..afb53ba20 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -29,11 +29,20 @@ #include <qwebenginesettings.h> #include <qnetworkrequest.h> #include <qdiriterator.h> +#include <qstackedlayout.h> #include <qtemporarydir.h> #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \ QVERIFY(actual == expect); +#define QTRY_COMPARE_WITH_TIMEOUT_FAIL_BLOCK(__expr, __expected, __timeout, __fail_block) \ +do { \ + QTRY_IMPL(((__expr) == (__expected)), __timeout);\ + if (__expr != __expected)\ + __fail_block\ + QCOMPARE((__expr), __expected); \ +} while (0) + class tst_QWebEngineView : public QObject { Q_OBJECT @@ -61,6 +70,10 @@ private Q_SLOTS: void setPalette_data(); void setPalette(); #endif + void doNotSendMouseKeyboardEventsWhenDisabled(); + void doNotSendMouseKeyboardEventsWhenDisabled_data(); + void stopSettingFocusWhenDisabled(); + void stopSettingFocusWhenDisabled_data(); }; // This will be called before the first test function is executed. @@ -591,5 +604,144 @@ void tst_QWebEngineView::renderingAfterMaxAndBack() #endif } +class KeyboardAndMouseEventRecordingWidget : public QWidget { +public: + explicit KeyboardAndMouseEventRecordingWidget(QWidget *parent = 0) : + QWidget(parent), m_eventCounter(0) {} + + bool event(QEvent *event) Q_DECL_OVERRIDE + { + QString eventString; + switch (event->type()) { + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::TabletMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + case QEvent::ContextMenu: + case QEvent::KeyPress: + case QEvent::KeyRelease: +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: +#endif + ++m_eventCounter; + event->setAccepted(true); + QDebug(&eventString) << event; + m_eventHistory.append(eventString); + return true; + default: + break; + } + return QWidget::event(event); + } + + void clearEventCount() + { + m_eventCounter = 0; + } + + int eventCount() + { + return m_eventCounter; + } + + void printEventHistory() + { + qDebug() << "Received events are:"; + for (int i = 0; i < m_eventHistory.size(); ++i) { + qDebug() << m_eventHistory[i]; + } + } + +private: + int m_eventCounter; + QVector<QString> m_eventHistory; +}; + +void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(int, resultEventCount); + + KeyboardAndMouseEventRecordingWidget parentWidget; + QWebEngineView webView(&parentWidget); + webView.setEnabled(viewEnabled); + parentWidget.setLayout(new QStackedLayout); + parentWidget.layout()->addWidget(&webView); + webView.resize(640, 480); + parentWidget.show(); + QTest::qWaitForWindowExposed(&webView); + + QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); + webView.setHtml("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + QTRY_COMPARE(loadSpy.count(), 1); + + // When the webView is enabled, the events are swallowed by it, and the parent widget + // does not receive any events, otherwise all events are processed by the parent widget. + parentWidget.clearEventCount(); + QTest::mousePress(parentWidget.windowHandle(), Qt::LeftButton); + QTest::mouseMove(parentWidget.windowHandle(), QPoint(100, 100)); + QTest::mouseRelease(parentWidget.windowHandle(), Qt::LeftButton, + Qt::KeyboardModifiers(), QPoint(100, 100)); + + // Wait a bit for the mouse events to be processed, so they don't interfere with the js focus + // below. + QTest::qWait(100); + evaluateJavaScriptSync(webView.page(), "document.getElementById(\"input\").focus()"); + QTest::keyPress(parentWidget.windowHandle(), Qt::Key_H); + + // Wait a bit for the key press to be handled. We have to do it, because the compare + // below could immediately finish successfully, without alloing for the events to be handled. + QTest::qWait(100); + QTRY_COMPARE_WITH_TIMEOUT_FAIL_BLOCK(parentWidget.eventCount(), resultEventCount, + 1000, parentWidget.printEventHistory();); +} + +void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled_data() +{ + QTest::addColumn<bool>("viewEnabled"); + QTest::addColumn<int>("resultEventCount"); + + QTest::newRow("enabled view receives events") << true << 0; + QTest::newRow("disabled view does not receive events") << false << 4; +} + +void tst_QWebEngineView::stopSettingFocusWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(bool, focusResult); + + QWebEngineView webView; + webView.resize(640, 480); + webView.show(); + webView.setEnabled(viewEnabled); + QTest::qWaitForWindowExposed(&webView); + + QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); + webView.setHtml("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + QTRY_COMPARE(loadSpy.count(), 1); + + QTRY_COMPARE_WITH_TIMEOUT(webView.hasFocus(), focusResult, 1000); + evaluateJavaScriptSync(webView.page(), "document.getElementById(\"input\").focus()"); + QTRY_COMPARE_WITH_TIMEOUT(webView.hasFocus(), focusResult, 1000); +} + +void tst_QWebEngineView::stopSettingFocusWhenDisabled_data() +{ + QTest::addColumn<bool>("viewEnabled"); + QTest::addColumn<bool>("focusResult"); + + QTest::newRow("enabled view gets focus") << true << true; + QTest::newRow("disabled view does not get focus") << false << false; +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro index 7543a4382..2f5416701 100644 --- a/tests/auto/widgets/widgets.pro +++ b/tests/auto/widgets/widgets.pro @@ -17,8 +17,3 @@ SUBDIRS += \ !contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile { SUBDIRS += qwebenginespellcheck } - -qtHaveModule(positioning) { - SUBDIRS += positionplugin - qwebenginepage.depends = positionplugin -} diff --git a/tools/buildscripts/find-included-moc-files b/tools/buildscripts/find-included-moc-files index e55f3824c..678b2d6f5 100755 --- a/tools/buildscripts/find-included-moc-files +++ b/tools/buildscripts/find-included-moc-files @@ -3,7 +3,9 @@ import re, sys, os includedMocs = set() -for f in filter(os.path.isfile, sys.argv[1:]): +dir = sys.argv[1] +files = sys.argv[2:] +for f in filter(os.path.isfile, [os.path.join(dir, f) for f in files]): inBlockComment = False for line in open(f).readlines(): m = re.search('#include "(moc_\w+.cpp)"', line) diff --git a/tools/buildscripts/find-mocables b/tools/buildscripts/find-mocables index 7c383cfec..4bfa311b5 100755 --- a/tools/buildscripts/find-mocables +++ b/tools/buildscripts/find-mocables @@ -3,7 +3,9 @@ import re, sys, os mocables = set() -for f in filter(os.path.isfile, sys.argv[1:]): +dir = sys.argv[1] +files = sys.argv[2:] +for f in filter(os.path.isfile, [os.path.join(dir, f) for f in files]): inBlockComment = False for line in open(f).readlines(): # Block comments handling diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index 679b282b3..7ef4b8545 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -26,7 +26,7 @@ defineTest(runConfigure) { !config_khr:skipBuild("khronos development headers appear to be missing (mesa/libegl1-mesa-dev)") REQUIRED_PACKAGES = dbus-1 fontconfig - contains(QT_CONFIG, xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst + !cross_compile: contains(QT_CONFIG, xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst contains(QT_CONFIG, pulseaudio): REQUIRED_PACKAGES += libpulse contains(QT_CONFIG, system-png): REQUIRED_PACKAGES += libpng contains(QT_CONFIG, system-harfbuzz): REQUIRED_PACKAGES += harfbuzz @@ -117,11 +117,16 @@ defineTest(finalizeConfigure) { } else { log("Proprietary codecs (H264, MP3).... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_proprietary_codecs)$${EOL}") } + qtHaveModule(positioning): { + log("Geolocation....................... Enabled$${EOL}") + } else { + log("Geolocation....................... Not enabled (Requires Qt Positioning module)$${EOL}") + } osx { use?(appstore_compliant_code) { log("AppStore Compliant ............... Enabled$${EOL}") } else { - log("AppStore Compliant ............... Not enabled (Default, enable with WEBENGINE_CONFIG += use_appstore_compliant_code)$${EOL}") + log("AppStore Compliant ............... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_appstore_compliant_code)$${EOL}") } } } diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf index e321efc87..ed6fa289b 100644 --- a/tools/qmake/mkspecs/features/functions.prf +++ b/tools/qmake/mkspecs/features/functions.prf @@ -149,19 +149,13 @@ defineReplace(extractCFlag) { } defineReplace(findMocables) { - input = $$1 - for (file, input): \ - infiles += $$absolute_path($$file, $$_PRO_FILE_PWD_) - mocables = $$system("python $$QTWEBENGINE_ROOT/tools/buildscripts/find-mocables $$infiles") - mocables = $$replace(mocables, $$re_escape($${_PRO_FILE_PWD_}/), '') + mocables = $$system("$$system_path(python $$QTWEBENGINE_ROOT/tools/buildscripts/find-mocables $$_PRO_FILE_PWD_ $$1)") + mocables = $$replace(mocables, $$re_escape($$system_path($${_PRO_FILE_PWD_}/)), '') return($$mocables) } defineReplace(findIncludedMocFiles) { - input = $$1 - for (file, input): \ - infiles += $$absolute_path($$file, $$_PRO_FILE_PWD_) - return($$system("python $$QTWEBENGINE_ROOT/tools/buildscripts/find-included-moc-files $$infiles")) + return($$system("$$system_path(python $$QTWEBENGINE_ROOT/tools/buildscripts/find-included-moc-files $$_PRO_FILE_PWD_ $$1)")) } defineReplace(mocOutput) { diff --git a/tools/qmake/mkspecs/features/gyp_generator.prf b/tools/qmake/mkspecs/features/gyp_generator.prf index eea11ef09..0ba6de09c 100644 --- a/tools/qmake/mkspecs/features/gyp_generator.prf +++ b/tools/qmake/mkspecs/features/gyp_generator.prf @@ -17,7 +17,7 @@ defineReplace(mocAction) { MOC_COMMAND = $$clean_path($$mocCmdBase()) MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(DEFINES)"), $$DEFINES_LIST) MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(INCPATH)"), $$INCPATH) - MOC_COMMAND = $$split(MOC_COMMAND, " ") + MOC_COMMAND = $$eval($$list($$MOC_COMMAND)) OUTPUT_FILE = $$MOC_GEN_DIR/$${OUTPUT_NAME} contents = " {" \ " 'action_name':'$$OUTPUT_NAME'," \ |