diff options
21 files changed, 327 insertions, 51 deletions
diff --git a/dist/changes-5.9.2 b/dist/changes-5.9.2 new file mode 100644 index 000000000..6cc9dbe37 --- /dev/null +++ b/dist/changes-5.9.2 @@ -0,0 +1,72 @@ +Qt 5.9.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* General * +**************************************************************************** + + - Chromium Snapshot: + * Security fixes from Chromium up to version 61.0.3163.79 + Including: CVE-2017-5092, CVE-2017-5093, CVE-2017-5095, CVE-2017-5097, + CVE-2017-5099, CVE-2017-5102, CVE-2017-5103, CVE-2017-5107, + CVE-2017-5112, CVE-2017-5114, CVE-2017-5117 and CVE-2017-5118 + * Fixed Skia to to render text correctly with FreeType 2.8.1 + * [QTBUG-50389] Fixed assert on some flash content + + - QtWebEngine: + * [QTBUG-57505] Handle --force-webrtc-ip-handling-policy on command-line + * [QTBUG-58306] Fixed handling of menu key + * [QTBUG-60790] Fixed dragging images to desktop + * [QTBUG-61354] Set referrer on download requests + * [QTBUG-61429] Fixed cancelling IME composition + * [QTBUG-61506] Stop searching when navigating away + * [QTBUG-61910] Fixed an issue where system proxy settings were not + picked up correctly + * [QTBUG-62112] Fixed upside-down rendering in software rendering mode + * [QTBUG-62112] Fixed rendering of content with preserve-3d in CSS + * [QTBUG-62311] Fixed hang when exiting with open combobox + * [QTBUG-62808] Handle --explicitly-allowed-ports on command-line + * [QTBUG-62898] Fixed accessing webchannels from document-creation + user-scripts after navigation. + * [QTBUG-62942] Fixed committing IME composition on touch events + + - QWebEngineView: + * [QTBUG-61621] Fixed propagation of unhandled key press events + + - WebEngineView: + * The callback version of printToPdf is now called with a proper + bytearray result instead of a PDF data in a javascript string. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + + - Linux: + * [QTBUG-61528, QTBUG-62673] Fixed various multilib build configurations + * [QTBUG-61846] Fixed host builds on Arm and MIPS + + - Windows: + * [QTBUG-60334] Fixed location of IME window + * [QTBUG-62146] Fixed following system font configuration + * [QTBUG-62200] Fixed assert on hover + * Allow WebGL to work with software OpenGL using the new command-line + argument --enable-webgl-software-rendering + + - macOS: + * [QTBUG-60605] Use OpenGL core-profile when the main application does diff --git a/examples/webengine/webengine.pro b/examples/webengine/webengine.pro index 3f55888cb..b20b8f118 100644 --- a/examples/webengine/webengine.pro +++ b/examples/webengine/webengine.pro @@ -3,5 +3,9 @@ TEMPLATE=subdirs SUBDIRS += \ customdialogs \ minimal \ - quicknanobrowser \ - recipebrowser + quicknanobrowser + +qtHaveModule(quickcontrols2) { + SUBDIRS += \ + recipebrowser +} diff --git a/examples/webenginewidgets/simplebrowser/browser.cpp b/examples/webenginewidgets/simplebrowser/browser.cpp index f5a69793f..c50974531 100644 --- a/examples/webenginewidgets/simplebrowser/browser.cpp +++ b/examples/webenginewidgets/simplebrowser/browser.cpp @@ -61,11 +61,15 @@ Browser::Browser() QObject::connect( QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); + QObject::connect( + &m_otrProfile, &QWebEngineProfile::downloadRequested, + &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); } -BrowserWindow *Browser::createWindow() +BrowserWindow *Browser::createWindow(bool offTheRecord) { - auto mainWindow = new BrowserWindow(this); + auto profile = offTheRecord ? &m_otrProfile : QWebEngineProfile::defaultProfile(); + auto mainWindow = new BrowserWindow(this, profile); m_windows.append(mainWindow); QObject::connect(mainWindow, &QObject::destroyed, [this, mainWindow]() { m_windows.removeOne(mainWindow); diff --git a/examples/webenginewidgets/simplebrowser/browser.h b/examples/webenginewidgets/simplebrowser/browser.h index 0ea30a7f5..9240cc987 100644 --- a/examples/webenginewidgets/simplebrowser/browser.h +++ b/examples/webenginewidgets/simplebrowser/browser.h @@ -54,6 +54,7 @@ #include "downloadmanagerwidget.h" #include <QVector> +#include <QWebEngineProfile> class BrowserWindow; @@ -64,12 +65,13 @@ public: QVector<BrowserWindow*> windows() { return m_windows; } - BrowserWindow *createWindow(); + BrowserWindow *createWindow(bool offTheRecord = false); DownloadManagerWidget &downloadManagerWidget() { return m_downloadManagerWidget; } private: QVector<BrowserWindow*> m_windows; DownloadManagerWidget m_downloadManagerWidget; + QWebEngineProfile m_otrProfile; }; #endif // BROWSER_H diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.cpp b/examples/webenginewidgets/simplebrowser/browserwindow.cpp index e114ae0f3..016d58afe 100644 --- a/examples/webenginewidgets/simplebrowser/browserwindow.cpp +++ b/examples/webenginewidgets/simplebrowser/browserwindow.cpp @@ -67,9 +67,10 @@ #include <QVBoxLayout> #include <QWebEngineProfile> -BrowserWindow::BrowserWindow(Browser *browser) +BrowserWindow::BrowserWindow(Browser *browser, QWebEngineProfile *profile) : m_browser(browser) - , m_tabWidget(new TabWidget(this)) + , m_profile(profile) + , m_tabWidget(new TabWidget(profile, this)) , m_progressBar(new QProgressBar(this)) , m_historyBackAction(nullptr) , m_historyForwardAction(nullptr) @@ -141,6 +142,7 @@ QMenu *BrowserWindow::createFileMenu(TabWidget *tabWidget) { QMenu *fileMenu = new QMenu(tr("&File")); fileMenu->addAction(tr("&New Window"), this, &BrowserWindow::handleNewWindowTriggered, QKeySequence::New); + fileMenu->addAction(tr("New &Incognito Window"), this, &BrowserWindow::handleNewIncognitoWindowTriggered); QAction *newTabAction = new QAction(tr("New &Tab"), this); newTabAction->setShortcuts(QKeySequence::AddTab); @@ -403,10 +405,14 @@ void BrowserWindow::handleWebActionEnabledChanged(QWebEnginePage::WebAction acti void BrowserWindow::handleWebViewTitleChanged(const QString &title) { + QString suffix = m_profile->isOffTheRecord() + ? tr("Qt Simple Browser (Incognito)") + : tr("Qt Simple Browser"); + if (title.isEmpty()) - setWindowTitle(tr("Qt Simple Browser")); + setWindowTitle(suffix); else - setWindowTitle(tr("%1 - Qt Simple Browser").arg(title)); + setWindowTitle(title + " - " + suffix); } void BrowserWindow::handleNewWindowTriggered() @@ -414,6 +420,11 @@ void BrowserWindow::handleNewWindowTriggered() m_browser->createWindow(); } +void BrowserWindow::handleNewIncognitoWindowTriggered() +{ + m_browser->createWindow(/* offTheRecord: */ true); +} + void BrowserWindow::handleFileOpenTriggered() { QUrl url = QFileDialog::getOpenFileUrl(this, tr("Open Web Resource"), QString(), diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.h b/examples/webenginewidgets/simplebrowser/browserwindow.h index 36f00605c..b522a6b9d 100644 --- a/examples/webenginewidgets/simplebrowser/browserwindow.h +++ b/examples/webenginewidgets/simplebrowser/browserwindow.h @@ -69,7 +69,7 @@ class BrowserWindow : public QMainWindow Q_OBJECT public: - BrowserWindow(Browser *browser); + BrowserWindow(Browser *browser, QWebEngineProfile *profile); QSize sizeHint() const override; TabWidget *tabWidget() const; WebView *currentTab() const; @@ -80,6 +80,7 @@ protected: private slots: void handleNewWindowTriggered(); + void handleNewIncognitoWindowTriggered(); void handleFileOpenTriggered(); void handleFindActionTriggered(); void handleShowWindowTriggered(); @@ -97,6 +98,7 @@ private: private: Browser *m_browser; + QWebEngineProfile *m_profile; TabWidget *m_tabWidget; QProgressBar *m_progressBar; QAction *m_historyBackAction; diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index 741ad864d..4f44d9f6c 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -202,9 +202,6 @@ \section1 Implementing WebPage Functionality - As mentioned earlier, each \c WebView contains a \c WebPage instance that - was created by using QWebEngineProfile::defaultProfile(). - We implement \c WebPage as a subclass of QWebEnginePage to enable HTTP, proxy authentication, and ignoring SSL certificate errors when accessing web pages: @@ -242,8 +239,16 @@ over to \c TabWidget::setUrl: \quotefromfile webenginewidgets/simplebrowser/browserwindow.cpp + \skipto BrowserWindow::BrowserWindow + \printline BrowserWindow::BrowserWindow + \skipto /^\{/ + \printline /^\{/ + \dots \skipto connect(m_urlLineEdit - \printline connect + \printuntil }); + \dots + \skipto /^\}/ + \printline /^\}/ The call is forwarded to the currently selected tab: @@ -255,6 +260,50 @@ The \c setUrl() method of \c WebView just forwards the \c url to the associated \c WebPage, which in turn starts the downloading of the page's content in the background. + \section1 Implementing Private Browsing + + \e{Private browsing}, \e{incognito mode}, or \e{off-the-record mode} is a + feature of many browsers where normally persistent data, such as cookies, + the HTTP cache, or browsing history, is kept only in memory, leaving no + trace on disk. In this example we will implement private browsing on the + window level with tabs in one window all in either normal or private mode. + Alternatively we could implement private browsing on the tab-level, with + some tabs in a window in normal mode, others in private mode. + + Implementing private browsing is quite easy using Qt WebEngine. All one has + to do is to create a new \l{QWebEngineProfile} and use it in the + \l{QWebEnginePage} instead of the default profile. In the example this new + profile is created and owned by the \c Browser object: + + \quotefromfile webenginewidgets/simplebrowser/browser.h + \skipto /^class Browser$/ + \printuntil public: + \dots + \skipto createWindow + \printline createWindow + \skipto private: + \printline private: + \dots + \skipto m_otrProfile + \printline m_otrProfile + \printline /^\};$/ + + The default constructor for \l{QWebEngineProfile} already puts it in + \e{off-the-record} mode. All that is left to do is to pass the appropriate + profile down to the appropriate \l QWebEnginePage objects. The \c Browser + object will hand to each new \c BrowserWindow either the global default + profile (see \l{QWebEngineProfile::defaultProfile}) or its own + off-the-record profile: + + \quotefromfile webenginewidgets/simplebrowser/browser.cpp + \skipto Browser::createWindow + \printuntil mainWindow = new BrowserWindow + \skipto return mainWindow + \printuntil /^\}/ + + The \c BrowserWindow and \c TabWidget objects will then ensure that all \l + QWebEnginePage objects contained in a window will use this profile. + \section1 Managing Downloads Downloads are associated with a \l QWebEngineProfile. Whenever a download is diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.cpp b/examples/webenginewidgets/simplebrowser/tabwidget.cpp index c3a90bce7..e7376c7a5 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/tabwidget.cpp @@ -55,8 +55,9 @@ #include <QTabBar> #include <QWebEngineProfile> -TabWidget::TabWidget(QWidget *parent) +TabWidget::TabWidget(QWebEngineProfile *profile, QWidget *parent) : QTabWidget(parent) + , m_profile(profile) { QTabBar *tabBar = this->tabBar(); tabBar->setTabsClosable(true); @@ -201,7 +202,7 @@ WebView *TabWidget::createTab() WebView *TabWidget::createBackgroundTab() { WebView *webView = new WebView; - WebPage *webPage = new WebPage(QWebEngineProfile::defaultProfile(), webView); + WebPage *webPage = new WebPage(m_profile, webView); webView->setPage(webPage); setupView(webView); int index = addTab(webView, tr("(Untitled)")); diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.h b/examples/webenginewidgets/simplebrowser/tabwidget.h index f33ecf897..5b09f2708 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.h +++ b/examples/webenginewidgets/simplebrowser/tabwidget.h @@ -65,7 +65,7 @@ class TabWidget : public QTabWidget Q_OBJECT public: - TabWidget(QWidget *parent = nullptr); + TabWidget(QWebEngineProfile *profile, QWidget *parent = nullptr); WebView *currentWebView() const; @@ -100,6 +100,8 @@ private slots: private: WebView *webView(int index) const; void setupView(WebView *webView); + + QWebEngineProfile *m_profile; }; #endif // TABWIDGET_H diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 05166536e..270595378 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -55,3 +55,11 @@ unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!static { SOURCES += qtbug-60565.cpp \ qtbug-61521.cpp } + +msvc { + # Create a list of object files that can be used as response file for the linker. + # This is done to simulate -whole-archive on MSVC. + QMAKE_POST_LINK = \ + "if exist $(DESTDIR_TARGET).objects del $(DESTDIR_TARGET).objects$$escape_expand(\\n\\t)" \ + "for %%a in ($(OBJECTS)) do echo $$shell_quote($$shell_path($$OUT_PWD))\\%%a >> $(DESTDIR_TARGET).objects" +} diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index 720db77bf..359e0b3d9 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -40,19 +40,23 @@ #include "content_main_delegate_qt.h" #include "base/command_line.h" +#include <base/i18n/rtl.h> #include "base/logging.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" +#include <chrome/grit/generated_resources.h> #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_paths.h" #include "ui/base/resource/resource_bundle.h" +#include <ui/base/webui/jstemplate_builder.h> #include "net/grit/net_resources.h" #include "net/base/net_module.h" #include "content_client_qt.h" #include "renderer/content_renderer_client_qt.h" +#include "type_conversion.h" #include "web_engine_library_info.h" #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) @@ -63,12 +67,38 @@ #include "ui/base/ui_base_switches.h" #endif +#include <QtCore/qcoreapplication.h> + namespace QtWebEngineCore { +// The logic of this function is based on chrome/common/net/net_resource_provider.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.Chromium file. +static std::string constructDirHeaderHTML() +{ + base::DictionaryValue dict; + dict.SetString("header", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_HEADER)); + dict.SetString("parentDirText", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_PARENT)); + dict.SetString("headerName", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_NAME)); + dict.SetString("headerSize", l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_SIZE)); + dict.SetString("headerDateModified", + l10n_util::GetStringUTF16(IDS_DIRECTORY_LISTING_DATE_MODIFIED)); + dict.SetString("language", l10n_util::GetLanguage(base::i18n::GetConfiguredLocale())); + dict.SetString("listingParsingErrorBoxText", + l10n_util::GetStringFUTF16(IDS_DIRECTORY_LISTING_PARSING_ERROR_BOX_TEXT, + toString16(QCoreApplication::applicationName()))); + dict.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr"); + std::string html = webui::GetI18nTemplateHtml( + ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML), + &dict); + return html; +} + static base::StringPiece PlatformResourceProvider(int key) { if (key == IDR_DIR_HEADER_HTML) { - base::StringPiece html_data = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML); - return html_data; + static std::string html_data = constructDirHeaderHTML(); + return base::StringPiece(html_data); } return base::StringPiece(); } diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 55b20cda2..78bb8baee 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -61,7 +61,9 @@ osx { QMAKE_LFLAGS_DEBUG -= /DEBUG QMAKE_LFLAGS_DEBUG += /DEBUG:FASTLINK } - QMAKE_LFLAGS += /WHOLEARCHIVE:$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib + # Simulate -whole-archive by passing the list of object files that belong to the public + # API library as response file to the linker. + QMAKE_LFLAGS += @$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib.objects } else { LIBS_PRIVATE += -Wl,-whole-archive -l$$api_library_name -Wl,-no-whole-archive } diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index d0d840ecb..d6ee87950 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -849,8 +849,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, // countering the scale of devicePixel-scaled tiles when rendering them // to the final surface. QMatrix4x4 matrix; - matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio, - 1 / m_chromiumCompositorData->frameDevicePixelRatio); + const float devicePixelRatio = m_chromiumCompositorData->frameDevicePixelRatio; + matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio); if (QSGTransformNode::matrix() != matrix) setMatrix(matrix); @@ -872,11 +872,19 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, frameData->resource_list.clear(); QScopedPointer<DelegatedNodeTreeHandler> nodeHandler; + const QSizeF viewportSizeInPt = apiDelegate->screenRect().size(); + const QSize viewportSize = (viewportSizeInPt * devicePixelRatio).toSize(); + // We first compare if the render passes from the previous frame data are structurally // equivalent to the render passes in the current frame data. If they are, we are going // to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree. - cc::CompositorFrame *previousFrameData = &m_chromiumCompositorData->previousFrameData; - const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData) || m_sceneGraphNodes.empty(); + // + // Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside + // of the visible area, we also have to rebuild the tree whenever the window is resized. + const bool buildNewTree = + !areRenderPassStructuresEqual(frameData, &m_chromiumCompositorData->previousFrameData) || + m_sceneGraphNodes.empty() || + viewportSize != m_previousViewportSize; m_chromiumCompositorData->previousFrameData = cc::CompositorFrame(); SGObjects previousSGObjects; @@ -904,10 +912,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, // All RenderPasses except the last one are rendered to an FBO. cc::RenderPass *rootRenderPass = frameData->render_pass_list.back().get(); - QRectF screenRectQt = apiDelegate->screenRect(); - gfx::Size thisSize(int(screenRectQt.width() * m_chromiumCompositorData->frameDevicePixelRatio), - int(screenRectQt.height() * m_chromiumCompositorData->frameDevicePixelRatio)); - + gfx::Rect viewportRect(toGfx(viewportSize)); for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) { cc::RenderPass *pass = frameData->render_pass_list.at(i).get(); @@ -939,12 +944,14 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, scissorRect = pass->output_rect; } else { renderPassParent = this; - scissorRect = gfx::Rect(thisSize); + scissorRect = viewportRect; scissorRect += rootRenderPass->output_rect.OffsetFromOrigin(); } - if (scissorRect.IsEmpty()) + if (scissorRect.IsEmpty()) { + holdResources(pass, resourceCandidates); continue; + } QSGNode *renderPassChain = nullptr; if (buildNewTree) @@ -967,8 +974,10 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, if (quadState->is_clipped) targetRect.Intersect(quadState->clip_rect); targetRect.Intersect(scissorRect); - if (targetRect.IsEmpty()) + if (targetRect.IsEmpty()) { + holdResources(quad, resourceCandidates); continue; + } if (quadState->sorting_context_id != currentSortingContextId) { flushPolygons(&polygonQueue, renderPassChain, @@ -1007,6 +1016,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, ResourceHolderIterator end = resourceCandidates.constEnd(); for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it) resourcesToRelease->push_back((*it)->returnResource()); + + m_previousViewportSize = viewportSize; } void DelegatedFrameNode::flushPolygons( @@ -1224,6 +1235,18 @@ ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHa return resource.data(); } +void DelegatedFrameNode::holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates) +{ + for (auto resource : quad->resources) + findAndHoldResource(resource, candidates); +} + +void DelegatedFrameNode::holdResources(const cc::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates) +{ + for (const auto &quad : pass->quad_list) + holdResources(quad, candidates); +} + QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate) { // QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree, diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index b83f4682a..c627cdf95 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -126,6 +126,8 @@ private: static void fenceAndUnlockQt(DelegatedFrameNode *frameNode); ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); + void holdResources(const cc::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); + void holdResources(const cc::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); QSGTexture *initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; @@ -143,6 +145,7 @@ private: bool m_contextShared; QScopedPointer<QOffscreenSurface> m_offsurface; #endif + QSize m_previousViewportSize; }; } // namespace QtWebEngineCore diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp index d0741506a..c976e8b04 100644 --- a/src/core/surface_factory_qt.cpp +++ b/src/core/surface_factory_qt.cpp @@ -56,7 +56,13 @@ #if defined(USE_OZONE) #include <EGL/egl.h> -#include <dlfcn.h> + +#ifndef QT_LIBDIR_EGL +#define QT_LIBDIR_EGL "/usr/lib" +#endif +#ifndef QT_LIBDIR_GLES2 +#define QT_LIBDIR_GLES2 QT_LIBDIR_EGL +#endif namespace QtWebEngineCore { @@ -92,21 +98,29 @@ base::NativeLibrary LoadLibrary(const base::FilePath& filename) { bool GLOzoneQt::LoadGLES2Bindings(gl::GLImplementation /*implementation*/) { - base::NativeLibrary eglgles2Library = dlopen(NULL, RTLD_LAZY); - if (!eglgles2Library) { - LOG(ERROR) << "Failed to open EGL/GLES2 context " << dlerror(); + base::FilePath libEGLPath = QtWebEngineCore::toFilePath(QT_LIBDIR_EGL); + libEGLPath = libEGLPath.Append("libEGL.so.1"); + base::NativeLibrary eglLibrary = LoadLibrary(libEGLPath); + if (!eglLibrary) + return false; + + base::FilePath libGLES2Path = QtWebEngineCore::toFilePath(QT_LIBDIR_GLES2); + libGLES2Path = libGLES2Path.Append("libGLESv2.so.2"); + base::NativeLibrary gles2Library = LoadLibrary(libGLES2Path); + if (!gles2Library) return false; - } - gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglgles2Library, "eglGetProcAddress")); + gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglLibrary, "eglGetProcAddress")); if (!get_proc_address) { LOG(ERROR) << "eglGetProcAddress not found."; - base::UnloadNativeLibrary(eglgles2Library); + base::UnloadNativeLibrary(eglLibrary); + base::UnloadNativeLibrary(gles2Library); return false; } gl::SetGLGetProcAddressProc(get_proc_address); - gl::AddGLNativeLibrary(eglgles2Library); + gl::AddGLNativeLibrary(eglLibrary); + gl::AddGLNativeLibrary(gles2Library); return true; } diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index d9ba735bd..eb7c9d48b 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -142,6 +142,11 @@ inline QRectF toQt(const gfx::RectF &rect) return QRectF(rect.x(), rect.y(), rect.width(), rect.height()); } +inline gfx::Size toGfx(const QSize &size) +{ + return gfx::Size(size.width(), size.height()); +} + inline QSize toQt(const gfx::Size &size) { return QSize(size.width(), size.height()); diff --git a/src/tools/qwebengine_convert_dict/main.cpp b/src/tools/qwebengine_convert_dict/main.cpp index e7dcc22d9..3a1a1ff64 100644 --- a/src/tools/qwebengine_convert_dict/main.cpp +++ b/src/tools/qwebengine_convert_dict/main.cpp @@ -30,6 +30,7 @@ #include <QTextStream> #include <QLibraryInfo> #include <QDir> +#include <QCoreApplication> // see also src/core/type_conversion.h inline base::FilePath::StringType toFilePathString(const QString &str) @@ -117,6 +118,11 @@ QString frameworkIcuDataPath() int main(int argc, char *argv[]) { + // Required only for making QLibraryInfo::location() return a valid path, when the application + // picks up a qt.conf file (which is the case for official Qt packages). + QCoreApplication app(argc, argv); + Q_UNUSED(app); + QTextStream out(stdout); if (argc != 3) { diff --git a/src/webengine/api/qquickwebenginefaviconprovider.cpp b/src/webengine/api/qquickwebenginefaviconprovider.cpp index b5ad6960a..3255f22be 100644 --- a/src/webengine/api/qquickwebenginefaviconprovider.cpp +++ b/src/webengine/api/qquickwebenginefaviconprovider.cpp @@ -70,7 +70,11 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url) QUrl providerUrl; providerUrl.setScheme(QStringLiteral("image")); providerUrl.setHost(identifier()); - providerUrl.setPath(QStringLiteral("/%1").arg(url.toString())); + providerUrl.setPath(QStringLiteral("/%1").arg(url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment))); + if (url.hasQuery()) + providerUrl.setQuery(url.query(QUrl::FullyDecoded)); + if (url.hasFragment()) + providerUrl.setFragment(url.fragment(QUrl::FullyDecoded)); return providerUrl; } diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index f844ddcd6..c4de46b67 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -145,24 +145,35 @@ using QtWebEngineCore::BrowserContextAdapter; \sa QWebEngineDownloadItem, QWebEnginePage::download() */ -QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext) +QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile) + : QObject(BrowserContextAdapter::globalQObjectRoot()) + , browserContextRef(browserContext) + , m_profile(profile) +{ + browserContextRef->addClient(m_profile); +} + +QWebEngineBrowserContext::~QWebEngineBrowserContext() +{ + Q_ASSERT(m_profile); + // In the case the user sets this profile as the parent of the interceptor + // it can be deleted before the browser-context still referencing it is. + browserContextRef->setRequestInterceptor(nullptr); + browserContextRef->removeClient(m_profile); +} + +QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext) : m_settings(new QWebEngineSettings()) , m_scriptCollection(new QWebEngineScriptCollection(new QWebEngineScriptCollectionPrivate(browserContext->userResourceController()))) - , m_browserContextRef(browserContext) + , m_browserContext(new QWebEngineBrowserContext(browserContext, this)) { - m_browserContextRef->addClient(this); m_settings->d_ptr->initDefaults(); } QWebEngineProfilePrivate::~QWebEngineProfilePrivate() { - // In the case the user sets this profile as the parent of the interceptor - // it can be deleted before the browser-context still referencing it is. - m_browserContextRef->setRequestInterceptor(nullptr); - delete m_settings; m_settings = 0; - m_browserContextRef->removeClient(this); Q_FOREACH (QWebEngineDownloadItem* download, m_ongoingDownloads) { if (download) @@ -172,6 +183,11 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate() m_ongoingDownloads.clear(); } +QSharedPointer<QtWebEngineCore::BrowserContextAdapter> QWebEngineProfilePrivate::browserContext() const +{ + return m_browserContext->browserContextRef; +} + void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) { m_ongoingDownloads.remove(downloadId); diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index c5a75f6d4..7f02307d3 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -65,15 +65,30 @@ class BrowserContextAdapter; QT_BEGIN_NAMESPACE +class QWebEngineProfilePrivate; class QWebEngineSettings; +// This is a wrapper class for BrowserContextAdapter. BrowserContextAdapter must be destructed before WebEngineContext +// is destructed. Therefore access it via the QWebEngineBrowserContext which parent is the WebEngineContext::globalQObject. +// This guarantees the destruction together with the WebEngineContext. +class QWebEngineBrowserContext : public QObject { +public: + QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile); + ~QWebEngineBrowserContext(); + + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextRef; + +private: + QWebEngineProfilePrivate *m_profile; +}; + class QWebEngineProfilePrivate : public QtWebEngineCore::BrowserContextAdapterClient { public: Q_DECLARE_PUBLIC(QWebEngineProfile) QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext); ~QWebEngineProfilePrivate(); - QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; } + QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const; QWebEngineSettings *settings() const { return m_settings; } void downloadDestroyed(quint32 downloadId); @@ -85,7 +100,7 @@ private: QWebEngineProfile *q_ptr; QWebEngineSettings *m_settings; QScopedPointer<QWebEngineScriptCollection> m_scriptCollection; - QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; + QPointer<QWebEngineBrowserContext> m_browserContext; QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads; }; diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro index 60e5cc11f..d76bf3579 100644 --- a/tests/auto/widgets/widgets.pro +++ b/tests/auto/widgets/widgets.pro @@ -4,7 +4,6 @@ QT_FOR_CONFIG += webengine-private TEMPLATE = subdirs SUBDIRS += \ - qwebengineaccessibility \ qwebenginedefaultsurfaceformat \ qwebenginedownloads \ qwebenginefaviconmanager \ @@ -17,6 +16,10 @@ SUBDIRS += \ qwebenginesettings \ qwebengineview +qtConfig(accessibility) { + SUBDIRS += qwebengineaccessibility +} + qtConfig(spellchecker):!cross_compile { !qtConfig(native-spellchecker) { SUBDIRS += qwebenginespellcheck |