diff options
author | Liang Qi <liang.qi@qt.io> | 2016-12-07 12:59:39 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-12-07 15:10:07 +0000 |
commit | 3ea2a12afa54e06726b3bfaf77eff46030fbdbdb (patch) | |
tree | 7b0d83a0dea3be2cef358ebaf691a6a5ac82abaf /src | |
parent | 6644981dfde2ad24186156d5c31a74c686b5557a (diff) | |
parent | c7f8e360da41df8b81004fe45f1582845a951c2b (diff) |
Merge "Merge remote-tracking branch 'origin/5.8' into dev" into refs/staging/dev
Diffstat (limited to 'src')
39 files changed, 450 insertions, 247 deletions
diff --git a/src/3rdparty b/src/3rdparty -Subproject f5a732820b31651bafc60cd64f85b85c7f82532 +Subproject 93b3786290ac16c95f15c95e2c2f3d8254171ab diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index bd2fecac2..a3806fc63 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -64,7 +64,7 @@ ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePing, content::RESOURCE ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker, content::RESOURCE_TYPE_SERVICE_WORKER) ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeCspReport, content::RESOURCE_TYPE_CSP_REPORT) ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePluginResource, content::RESOURCE_TYPE_PLUGIN_RESOURCE) -ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeUnknown, content::RESOURCE_TYPE_LAST_TYPE) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeLast, content::RESOURCE_TYPE_LAST_TYPE) ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::LinkNavigation, QWebEngineUrlRequestInfo::NavigationTypeLink) ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::TypedNavigation, QWebEngineUrlRequestInfo::NavigationTypeTyped) @@ -175,6 +175,9 @@ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPriva HTTP POST requests to specified servers. (Added in Qt 5.7) \value ResourceTypePluginResource A resource requested by a plugin. (Added in Qt 5.7) \value ResourceTypeUnknown Unknown request type. + + \note For forward compatibility all values not matched should be treated as unknown, + not just \c ResourceTypeUnknown. */ /*! diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index d75ceabf6..52463a1b3 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -75,7 +75,10 @@ public: ResourceTypeServiceWorker, // the main resource of a service worker. ResourceTypeCspReport, // Content Security Policy (CSP) violation report ResourceTypePluginResource, // A resource requested by a plugin - ResourceTypeUnknown +#ifndef Q_QDOC + ResourceTypeLast, +#endif + ResourceTypeUnknown = 255 }; enum NavigationType { diff --git a/src/core/common/qt_ipc_logging.cpp b/src/core/common/qt_ipc_logging.cpp new file mode 100644 index 000000000..124124de1 --- /dev/null +++ b/src/core/common/qt_ipc_logging.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED + +#if defined(IPC_MESSAGE_LOG_ENABLED) +#define IPC_MESSAGE_MACROS_LOG_ENABLED +#include "content/public/common/content_ipc_logging.h" +#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \ + content::RegisterIPCLogger(msg_id, logger) +#include "common/qt_messages.h" +#endif diff --git a/src/core/config/common.pri b/src/core/config/common.pri index 7a9656fca..b5bb23684 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -2,8 +2,6 @@ # Trigger Qt-specific build conditions. GYP_CONFIG += use_qt=1 -# Enable printing. We enable preview because we use preview logic even if we don't support preview. -GYP_CONFIG += enable_basic_printing=1 enable_print_preview=1 # We do not want to ship more external binary blobs, so let v8 embed its startup data. GYP_CONFIG += v8_use_external_startup_data=0 # WebSpeech requires Google API keys and adds dependencies on speex and flac. diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index e28d7eb7c..23044619b 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -5,6 +5,8 @@ include(linux.pri) GYP_CONFIG += \ desktop_linux=1 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 clang { diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index be037cbde..4111236ed 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -26,6 +26,8 @@ GYP_CONFIG += \ make_clang_dir=\"$${QMAKE_CLANG_DIR}\" \ clang_use_chrome_plugins=0 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 # Force touch API is used in 49-based Chromium, which is included starting with 10.10.3 SDK, so we diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index 9564cf9b7..a1c116ff8 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -7,6 +7,8 @@ GYP_CONFIG += \ remoting=0 \ use_ash=0 \ enable_widevine=1 \ + enable_basic_printing=1 \ + enable_print_preview=1 \ enable_pdf=1 # Libvpx build needs additional search path on Windows. diff --git a/src/core/core_common.pri b/src/core/core_common.pri index 721e8c71a..9c29aea71 100644 --- a/src/core/core_common.pri +++ b/src/core/core_common.pri @@ -10,4 +10,3 @@ CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() INCLUDEPATH += $$CHROMIUM_SRC_DIR qtHaveModule(positioning):QT += positioning -qtHaveModule(printsupport):QT += printsupport diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 2fae21c4d..a09683ba6 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -53,6 +53,7 @@ SOURCES = \ clipboard_qt.cpp \ color_chooser_qt.cpp \ color_chooser_controller.cpp \ + common/qt_ipc_logging.cpp \ common/qt_messages.cpp \ common/user_script_data.cpp \ content_client_qt.cpp \ @@ -74,6 +75,7 @@ SOURCES = \ native_web_keyboard_event_qt.cpp \ network_delegate_qt.cpp \ ozone_platform_eglfs.cpp \ + pdfium_document_wrapper_qt.cpp \ permission_manager_qt.cpp \ process_main.cpp \ proxy_config_service_qt.cpp \ @@ -154,6 +156,7 @@ HEADERS = \ media_capture_devices_dispatcher.h \ network_delegate_qt.h \ ozone_platform_eglfs.h \ + pdfium_document_wrapper_qt.h \ permission_manager_qt.h \ process_main.h \ proxy_config_service_qt.h \ @@ -210,8 +213,3 @@ qtHaveModule(positioning) { HEADERS += location_provider_qt.h DEFINES += QT_USE_POSITIONING=1 } - -qtHaveModule(printsupport) { - SOURCES += pdfium_printing_wrapper_qt.cpp - HEADERS += pdfium_printing_wrapper_qt.h -} diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index ed54f2ec8..9b4c415c9 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -58,7 +58,7 @@ namespace QtWebEngineCore { -int pageTransitionToNavigationType(ui::PageTransition transition) +WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) { int32_t qualifier = ui::PageTransitionGetQualifier(transition); @@ -81,6 +81,18 @@ int pageTransitionToNavigationType(ui::PageTransition transition) } } +QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) +{ + if (resourceType >= 0 && resourceType < content::ResourceType(QWebEngineUrlRequestInfo::ResourceTypeLast)) + return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); + return QWebEngineUrlRequestInfo::ResourceTypeUnknown; +} + +QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) +{ + return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); +} + NetworkDelegateQt::NetworkDelegateQt(URLRequestContextGetterQt *requestContext) : m_requestContextGetter(requestContext) { @@ -94,7 +106,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); content::ResourceType resourceType = content::RESOURCE_TYPE_LAST_TYPE; - int navigationType = QWebEngineUrlRequestInfo::NavigationTypeOther; + WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; if (resourceInfo) { resourceType = resourceInfo->GetResourceType(); @@ -105,11 +117,11 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_requestInterceptor; if (interceptor) { - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType) - , static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType) - , qUrl - , toQt(request->first_party_for_cookies()) - , QByteArray::fromStdString(request->method())); + QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), + toQt(navigationType), + qUrl, + toQt(request->first_party_for_cookies()), + QByteArray::fromStdString(request->method())); QWebEngineUrlRequestInfo requestInfo(infoPrivate); interceptor->interceptRequest(requestInfo); if (requestInfo.changed()) { diff --git a/src/core/pdfium_printing_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp index fceb381af..7c43c77db 100644 --- a/src/core/pdfium_printing_wrapper_qt.cpp +++ b/src/core/pdfium_document_wrapper_qt.cpp @@ -36,23 +36,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#include "pdfium_printing_wrapper_qt.h" +#if defined (ENABLE_PDF) +#include "pdfium_document_wrapper_qt.h" #include <QtCore/qhash.h> #include <QtGui/qimage.h> #include <QtGui/qpainter.h> -#include <QtPrintSupport/qprinter.h> #include "third_party/pdfium/public/fpdf_doc.h" #include "third_party/pdfium/public/fpdfview.h" namespace QtWebEngineCore { -int PdfiumPrintingWrapperQt::m_libraryUsers = 0; +int PdfiumDocumentWrapperQt::m_libraryUsers = 0; -class PDFiumPageWrapper { +class QWEBENGINE_EXPORT PdfiumPageWrapperQt { public: - PDFiumPageWrapper(void *data, int pageIndex, int targetWidth, int targetHeight) + PdfiumPageWrapperQt(void *data, int pageIndex, int targetWidth, int targetHeight) : m_pageData(FPDF_LoadPage(data, pageIndex)) , m_width(FPDF_GetPageWidth(m_pageData)) , m_height(FPDF_GetPageHeight(m_pageData)) @@ -61,7 +60,7 @@ public: { } - PDFiumPageWrapper() + PdfiumPageWrapperQt() : m_pageData(nullptr) , m_width(-1) , m_height(-1) @@ -70,7 +69,7 @@ public: { } - virtual ~PDFiumPageWrapper() + virtual ~PdfiumPageWrapperQt() { FPDF_ClosePage(m_pageData); } @@ -125,111 +124,49 @@ private: }; -PdfiumPrintingWrapperQt::PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password) +PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize& imageSize, const char *password) + : m_imageSize(imageSize * 2.0) { - Q_ASSERT(pdfData); - Q_ASSERT(size); - if (m_libraryUsers++ == 0) - FPDF_InitLibrary(); + Q_ASSERT(pdfData); + Q_ASSERT(size); + if (m_libraryUsers++ == 0) + FPDF_InitLibrary(); - m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); - m_pageCount = FPDF_GetPageCount(m_documentHandle); + m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); + m_pageCount = FPDF_GetPageCount(m_documentHandle); } -bool PdfiumPrintingWrapperQt::printOnPrinter(QPrinter &printer) +QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) { if (!m_documentHandle || !m_pageCount) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - qWarning("Failure to print on printer %ls: invalid document.\n", qUtf16Printable(printer.printerName())); -#endif - return false; - } - - int toPage = printer.toPage(); - int fromPage = printer.fromPage(); - bool ascendingOrder = true; - - if (fromPage == 0 && toPage == 0) { - fromPage = 1; - toPage = m_pageCount; + qWarning("Failure to generate QImage from invalid or empty PDF document."); + return QImage(); } - fromPage = qMax(1, fromPage); - toPage = qMin(m_pageCount, toPage); - if (printer.pageOrder() == QPrinter::LastPageFirst) { - qSwap(fromPage, toPage); - ascendingOrder = false; + if (static_cast<int>(index) >= m_pageCount) { + qWarning("Failure to generate QImage from PDF data: index out of bounds."); + return QImage(); } - int documentCopies = printer.copyCount(); - int pageCopies = 1; - if (printer.collateCopies()) { - pageCopies = documentCopies; - documentCopies = 1; + PdfiumPageWrapperQt *pageWrapper = nullptr; + if (!m_cachedPages.contains(index)) { + pageWrapper = new PdfiumPageWrapperQt(m_documentHandle, index, + m_imageSize.width(), m_imageSize.height()); + m_cachedPages.insert(index, pageWrapper); + } else { + pageWrapper = m_cachedPages.value(index); } - QRect printerPageRect = printer.pageRect(); - int doubledPrinterWidth = 2 * printerPageRect.width(); - int doubledPrinterHeight = 2 * printerPageRect.height(); - - QPainter painter; - if (!painter.begin(&printer)) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - qWarning("Failure to print on printer %ls: Could not open printer for painting.\n", qUtf16Printable(printer.printerName())); -#endif - return false; - } - - QHash<int, PDFiumPageWrapper*> cachedPages; - for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { - int currentPageIndex = fromPage; - while (true) { - for (int printedPages = 0; printedPages < pageCopies; printedPages++) { - if (printer.printerState() == QPrinter::Aborted - || printer.printerState() == QPrinter::Error) - return false; - - PDFiumPageWrapper *currentPageWrapper; - if (!cachedPages.contains(currentPageIndex - 1)) { - currentPageWrapper - = new PDFiumPageWrapper(m_documentHandle, currentPageIndex - 1 - , doubledPrinterWidth, doubledPrinterHeight); - cachedPages.insert(currentPageIndex - 1, currentPageWrapper); - } else { - currentPageWrapper = cachedPages.value(currentPageIndex - 1); - } - - QImage currentImage = currentPageWrapper->image(); - painter.drawImage(printerPageRect, currentImage, currentImage.rect()); - if (printedPages < pageCopies - 1) - printer.newPage(); - } - - if (currentPageIndex == toPage) - break; - - if (ascendingOrder) - currentPageIndex++; - else - currentPageIndex--; - - printer.newPage(); - } - if (printedDocuments < documentCopies - 1) - printer.newPage(); - } - painter.end(); - - qDeleteAll(cachedPages); - - return true; + return pageWrapper->image(); } -PdfiumPrintingWrapperQt::~PdfiumPrintingWrapperQt() +PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() { + qDeleteAll(m_cachedPages); FPDF_CloseDocument(m_documentHandle); if (--m_libraryUsers == 0) FPDF_DestroyLibrary(); } } +#endif // defined (ENABLE_PDF) diff --git a/src/core/pdfium_printing_wrapper_qt.h b/src/core/pdfium_document_wrapper_qt.h index 3aaf2b461..42ac94a28 100644 --- a/src/core/pdfium_printing_wrapper_qt.h +++ b/src/core/pdfium_document_wrapper_qt.h @@ -37,30 +37,35 @@ ** ****************************************************************************/ -#ifndef PDFIUM_PRINTING_WRAPPER_QT_H -#define PDFIUM_PRINTING_WRAPPER_QT_H +#ifndef PDFIUM_DOCUMENT_WRAPPER_QT_H +#define PDFIUM_DOCUMENT_WRAPPER_QT_H -#include <QtCore/qglobal.h> +#if defined(ENABLE_PDF) +#include "qtwebenginecoreglobal.h" -QT_BEGIN_NAMESPACE -class QPrinter; -QT_END_NAMESPACE +#include <QtCore/qglobal.h> +#include <QtCore/qhash.h> +#include <QtGui/qimage.h> namespace QtWebEngineCore { +class PdfiumPageWrapperQt; -class PdfiumPrintingWrapperQt +class QWEBENGINE_EXPORT PdfiumDocumentWrapperQt { public: - PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password = nullptr); - virtual ~PdfiumPrintingWrapperQt(); - bool printOnPrinter(QPrinter &printer); + PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, const char *password = nullptr); + virtual ~PdfiumDocumentWrapperQt(); + QImage pageAsQImage(size_t index); int pageCount() const { return m_pageCount; } private: static int m_libraryUsers; - void *m_documentHandle; int m_pageCount; + void *m_documentHandle; + QSize m_imageSize; + QHash<int, PdfiumPageWrapperQt*> m_cachedPages; }; } // namespace QtWebEngineCore -#endif // PDFIUM_PRINTING_WRAPPER_QT_H +#endif // defined (ENABLE_PDF) +#endif // PDFIUM_DOCUMENT_WRAPPER_QT_H diff --git a/src/core/render_view_observer_host_qt.cpp b/src/core/render_view_observer_host_qt.cpp index c03cecb38..643eba007 100644 --- a/src/core/render_view_observer_host_qt.cpp +++ b/src/core/render_view_observer_host_qt.cpp @@ -71,8 +71,6 @@ bool RenderViewObserverHostQt::OnMessageReceived(const IPC::Message& message) onDidFetchDocumentMarkup) IPC_MESSAGE_HANDLER(RenderViewObserverHostQt_DidFetchDocumentInnerText, onDidFetchDocumentInnerText) - IPC_MESSAGE_HANDLER(RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout, - onDidFirstVisuallyNonEmptyLayout) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -89,11 +87,4 @@ void RenderViewObserverHostQt::onDidFetchDocumentInnerText(quint64 requestId, co m_adapterClient->didFetchDocumentInnerText(requestId, toQt(innerText)); } -void RenderViewObserverHostQt::onDidFirstVisuallyNonEmptyLayout() -{ - RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView()); - if (rwhv) - rwhv->didFirstVisuallyNonEmptyLayout(); -} - } // namespace QtWebEngineCore diff --git a/src/core/render_view_observer_host_qt.h b/src/core/render_view_observer_host_qt.h index f352be7b9..42d232b01 100644 --- a/src/core/render_view_observer_host_qt.h +++ b/src/core/render_view_observer_host_qt.h @@ -63,7 +63,6 @@ private: bool OnMessageReceived(const IPC::Message& message) Q_DECL_OVERRIDE; void onDidFetchDocumentMarkup(quint64 requestId, const base::string16& markup); void onDidFetchDocumentInnerText(quint64 requestId, const base::string16& innerText); - void onDidFirstVisuallyNonEmptyLayout(); WebContentsAdapterClient *m_adapterClient; }; diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 097dda1cd..70ffe0dcb 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -236,7 +236,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget , m_touchMotionStarted(false) , m_chromiumCompositorData(new ChromiumCompositorData) , m_needsDelegatedFrameAck(false) - , m_didFirstVisuallyNonEmptyLayout(false) + , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) , m_imeInProgress(false) , m_receivedEmptyImeText(false) @@ -676,9 +676,11 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, c m_delegate->update(); - if (m_didFirstVisuallyNonEmptyLayout) { + if (m_loadVisuallyCommittedState == NotCommitted) { + m_loadVisuallyCommittedState = DidFirstCompositorFrameSwap; + } else if (m_loadVisuallyCommittedState == DidFirstVisuallyNonEmptyPaint) { m_adapterClient->loadVisuallyCommitted(); - m_didFirstVisuallyNonEmptyLayout = false; + m_loadVisuallyCommittedState = NotCommitted; } if (scrollOffsetChanged) @@ -1244,9 +1246,4 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) } } -void RenderWidgetHostViewQt::didFirstVisuallyNonEmptyLayout() -{ - m_didFirstVisuallyNonEmptyLayout = true; -} - } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index d6c77fada..0b2d7bc9d 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -104,6 +104,12 @@ class RenderWidgetHostViewQt #endif // QT_NO_ACCESSIBILITY { public: + enum LoadVisuallyCommittedState { + NotCommitted, + DidFirstVisuallyNonEmptyPaint, + DidFirstCompositorFrameSwap + }; + RenderWidgetHostViewQt(content::RenderWidgetHost* widget); ~RenderWidgetHostViewQt(); @@ -193,7 +199,8 @@ public: #ifndef QT_NO_ACCESSIBILITY virtual void accessibilityActiveChanged(bool active) Q_DECL_OVERRIDE; #endif // QT_NO_ACCESSIBILITY - void didFirstVisuallyNonEmptyLayout(); + LoadVisuallyCommittedState getLoadVisuallyCommittedState() const { return m_loadVisuallyCommittedState; } + void setLoadVisuallyCommittedState(LoadVisuallyCommittedState state) { m_loadVisuallyCommittedState = state; } gfx::SizeF lastContentsSize() const { return m_lastContentsSize; } @@ -218,7 +225,7 @@ private: QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; cc::ReturnedResourceArray m_resourcesToRelease; bool m_needsDelegatedFrameAck; - bool m_didFirstVisuallyNonEmptyLayout; + LoadVisuallyCommittedState m_loadVisuallyCommittedState; uint32_t m_pendingOutputSurfaceId; QMetaObject::Connection m_adapterClientDestroyedConnection; diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp index 393b4752c..97485afad 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/render_view_observer_qt.cpp @@ -83,11 +83,6 @@ void RenderViewObserverQt::onSetBackgroundColor(quint32 color) render_view()->GetWebFrameWidget()->setBaseBackgroundColor(color); } -void RenderViewObserverQt::OnFirstVisuallyNonEmptyLayout() -{ - Send(new RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout(routing_id())); -} - bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message) { bool handled = true; diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h index b62c815af..538ebea8a 100644 --- a/src/core/renderer/render_view_observer_qt.h +++ b/src/core/renderer/render_view_observer_qt.h @@ -57,7 +57,6 @@ private: void onFetchDocumentInnerText(quint64 requestId); void onSetBackgroundColor(quint32 color); - void OnFirstVisuallyNonEmptyLayout() Q_DECL_OVERRIDE; void OnDestruct() Q_DECL_OVERRIDE { } virtual bool OnMessageReceived(const IPC::Message& message) Q_DECL_OVERRIDE; diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index 887222285..d093efd0a 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -229,6 +229,9 @@ void URLRequestCustomJobShared::setReplyDevice(QIODevice *device) if (m_device && !m_device->isReadable()) m_device->open(QIODevice::ReadOnly); + qint64 size = m_device ? m_device->size() : -1; + if (size > 0) + m_job->set_expected_content_size(size); if (m_device && m_device->isReadable()) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestCustomJobShared::notifyStarted, m_weakFactory.GetWeakPtr())); else diff --git a/src/core/url_request_qrc_job_qt.cpp b/src/core/url_request_qrc_job_qt.cpp index ffe9b6dc6..97460f0b7 100644 --- a/src/core/url_request_qrc_job_qt.cpp +++ b/src/core/url_request_qrc_job_qt.cpp @@ -120,6 +120,7 @@ void URLRequestQrcJobQt::startGetHead() // Open file if (m_file.open(QIODevice::ReadOnly)) { m_remainingBytes = m_file.size(); + set_expected_content_size(m_remainingBytes); // Notify that the headers are complete NotifyHeadersComplete(); } else { diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index fadbd6d2e..cafaad93d 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -50,7 +50,7 @@ #include "browser_context_qt.h" #include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" -#include "pdfium_printing_wrapper_qt.h" +#include "pdfium_document_wrapper_qt.h" #include "print_view_manager_qt.h" #include "qwebenginecallback_p.h" #include "renderer_host/web_channel_ipc_transport_host.h" @@ -92,9 +92,6 @@ #include <QtGui/qaccessible.h> #include <QtGui/qdrag.h> #include <QtGui/qpixmap.h> -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -#include <QtPrintSupport/qprinter.h> -#endif // QT_NO_PRINTER #include <QtWebChannel/QWebChannel> namespace QtWebEngineCore { @@ -188,21 +185,9 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, int requestId, const std::vector<char>& result) { - if (requestId) { + if (requestId) adapterClient->didPrintPage(requestId, QByteArray(result.data(), result.size())); - } -} - -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -static void callbackOnPrintingOnPrinterFinished(WebContentsAdapterClient *adapterClient, int requestId, QPrinter *printer, const std::vector<char> &result) -{ - if (requestId) { - PdfiumPrintingWrapperQt printWrapper(result.data(), result.size()); - bool printerResult = printWrapper.printOnPrinter(*printer); - adapterClient->didPrintPageOnPrinter(requestId, printerResult); - } } -#endif // QT_NO_PRINTER static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { @@ -978,14 +963,14 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString #endif // if defined(ENABLE_BASIC_PRINTING) } -quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout) +quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout, const bool colorMode) { #if defined(ENABLE_BASIC_PRINTING) Q_D(WebContentsAdapter); PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished , d->adapterClient , d->nextRequestId); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, true + PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, colorMode , callback); return d->nextRequestId++; #else @@ -993,23 +978,6 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo #endif // if defined(ENABLE_BASIC_PRINTING) } -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -quint64 WebContentsAdapter::printOnPrinterCallbackResult(QPrinter *printer) -{ -#if defined(ENABLE_BASIC_PRINTING) - Q_D(WebContentsAdapter); - PrintViewManagerQt::PrintToPDFCallback callback - = base::Bind(&callbackOnPrintingOnPrinterFinished, d->adapterClient - , d->nextRequestId, printer); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback( - printer->pageLayout(), printer->colorMode() == QPrinter::Color, callback); - return d->nextRequestId++; -#else - return 0; -#endif // if defined(ENABLE_BASIC_PRINTING) -} -#endif // QT_NO_PRINTER - QPointF WebContentsAdapter::lastScrollOffset() const { Q_D(const WebContentsAdapter); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 7a109770e..3befe6d27 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -58,9 +58,6 @@ class QAccessibleInterface; class QDragEnterEvent; class QDragMoveEvent; class QPageLayout; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) -class QPrinter; -#endif // QT_NO_PRINTER class QString; class QWebChannel; QT_END_NAMESPACE @@ -175,11 +172,7 @@ public: void leaveDrag(); void initUpdateDragCursorMessagePollingTimer(); void printToPDF(const QPageLayout&, const QString&); - quint64 printToPDFCallbackResult(const QPageLayout &); - -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - quint64 printOnPrinterCallbackResult(QPrinter *printer); -#endif + quint64 printToPDFCallbackResult(const QPageLayout &, const bool colorMode = true); // meant to be used within WebEngineCore only content::WebContents *webContents() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 85a379409..4e15df753 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -347,9 +347,6 @@ public: virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; virtual void didFindText(quint64 requestId, int matchCount) = 0; virtual void didPrintPage(quint64 requestId, const QByteArray &result) = 0; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - virtual void didPrintPageOnPrinter(quint64 requestId, bool result) = 0; -#endif virtual void passOnFocus(bool reverse) = 0; // returns the last QObject (QWidget/QQuickItem) based object in the accessibility // hierarchy before going into the BrowserAccessibility tree diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 36acfe62e..87badc189 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -51,6 +51,7 @@ #include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" #include "network_delegate_qt.h" +#include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" #include "web_contents_adapter_p.h" @@ -387,6 +388,21 @@ void WebContentsDelegateQt::WasShown() web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetRenderProcessHost()->GetID()); } +void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint() +{ + RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView()); + if (!rwhv) + return; + + RenderWidgetHostViewQt::LoadVisuallyCommittedState loadVisuallyCommittedState = rwhv->getLoadVisuallyCommittedState(); + if (loadVisuallyCommittedState == RenderWidgetHostViewQt::NotCommitted) { + rwhv->setLoadVisuallyCommittedState(RenderWidgetHostViewQt::DidFirstVisuallyNonEmptyPaint); + } else if (loadVisuallyCommittedState == RenderWidgetHostViewQt::DidFirstCompositorFrameSwap) { + m_viewClient->loadVisuallyCommitted(); + rwhv->setLoadVisuallyCommittedState(RenderWidgetHostViewQt::NotCommitted); + } +} + void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) { Q_UNUSED(user_gesture); @@ -422,7 +438,7 @@ void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingO m_viewClient->runGeolocationPermissionRequest(requestingOrigin); } -extern int pageTransitionToNavigationType(ui::PageTransition transition); +extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame) { diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index dad1e50f1..683b14ddf 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -135,6 +135,7 @@ public: virtual void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) Q_DECL_OVERRIDE; virtual void DidNavigateAnyFrame(content::RenderFrameHost *render_frame_host, const content::LoadCommittedDetails &details, const content::FrameNavigateParams ¶ms) Q_DECL_OVERRIDE; virtual void WasShown() Q_DECL_OVERRIDE; + virtual void DidFirstVisuallyNonEmptyPaint() Q_DECL_OVERRIDE; void overrideWebPreferences(content::WebContents *, content::WebPreferences*); void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 491835e45..152859bee 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -240,17 +240,15 @@ QObject *WebEngineContext::globalQObject() #define CHROMIUM_VERSION // This is solely to keep Qt Creator happy. #endif +const static char kChromiumFlagsEnv[] = "QTWEBENGINE_CHROMIUM_FLAGS"; +const static char kDisableSandboxEnv[] = "QTWEBENGINE_DISABLE_SANDBOX"; + WebEngineContext::WebEngineContext() : m_mainDelegate(new ContentMainDelegateQt) , m_contentRunner(content::ContentMainRunner::Create()) , m_browserRunner(content::BrowserMainRunner::Create()) , m_globalQObject(new QObject()) { - QStringList appArgs = QCoreApplication::arguments(); - bool useEmbeddedSwitches = appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); -#if defined(QTWEBENGINE_EMBEDDED_SWITCHES) - useEmbeddedSwitches = !appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); -#endif #ifdef Q_OS_LINUX // Call qputenv before BrowserMainRunnerImpl::Initialize is called. @@ -261,32 +259,35 @@ WebEngineContext::WebEngineContext() // Allow us to inject javascript like any webview toolkit. content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView(); -#if defined(Q_OS_WIN) - // We must initialize the command line with the UTF-16 arguments vector we got from - // QCoreApplication. CommandLine::Init ignores its arguments on Windows and calls - // GetCommandLineW() instead. base::CommandLine::CreateEmpty(); base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); + QStringList appArgs = QCoreApplication::arguments(); + if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { + appArgs = appArgs.mid(0, 1); // Take application name and drop the rest + appArgs.append(QString::fromLocal8Bit(qgetenv(kChromiumFlagsEnv)).split(' ')); + } + + bool useEmbeddedSwitches = false; +#if defined(QTWEBENGINE_EMBEDDED_SWITCHES) + useEmbeddedSwitches = !appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); +#else + useEmbeddedSwitches = appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); +#endif base::CommandLine::StringVector argv; argv.resize(appArgs.size()); - std::transform(appArgs.constBegin(), appArgs.constEnd(), argv.begin(), &toString16); - parsedCommandLine->InitFromArgv(argv); +#if defined(Q_OS_WIN) + for (int i = 0; i < appArgs.size(); ++i) + argv[i] = toString16(appArgs[i]); #else - QVector<QByteArray> args; - Q_FOREACH (const QString& arg, appArgs) - args << arg.toUtf8(); - - QVector<const char*> argv(args.size()); - for (int i = 0; i < args.size(); ++i) - argv[i] = args[i].constData(); - base::CommandLine::Init(argv.size(), argv.constData()); - base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); + for (int i = 0; i < appArgs.size(); ++i) + argv[i] = appArgs[i].toStdString(); #endif + parsedCommandLine->InitFromArgv(argv); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); // Enable sandboxing on OS X and Linux (Desktop / Embedded) by default. - bool disable_sandbox = qEnvironmentVariableIsSet("QTWEBENGINE_DISABLE_SANDBOX"); + bool disable_sandbox = qEnvironmentVariableIsSet(kDisableSandboxEnv); if (!disable_sandbox) { #if defined(Q_OS_WIN) parsedCommandLine->AppendSwitch(switches::kNoSandbox); @@ -328,7 +329,14 @@ WebEngineContext::WebEngineContext() #ifndef QT_NO_OPENGL if (!usingANGLE() && !usingSoftwareDynamicGL() && !usingQtQuick2DRenderer()) { if (qt_gl_global_share_context() && qt_gl_global_share_context()->isValid()) { - if (!strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext")) { + // If the native handle is QEGLNativeContext try to use GL ES/2, if there is no native handle + // assume we are using wayland and try GL ES/2, and finally Ozone demands GL ES/2 too. + if (qt_gl_global_share_context()->nativeHandle().isNull() +#ifdef USE_OZONE + || true +#endif + || !strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext")) + { if (qt_gl_global_share_context()->isOpenGLES()) { glType = gl::kGLImplementationEGLName; } else { diff --git a/src/webengine/api/qquickwebenginefaviconprovider.cpp b/src/webengine/api/qquickwebenginefaviconprovider.cpp index fe8436d6c..b5ad6960a 100644 --- a/src/webengine/api/qquickwebenginefaviconprovider.cpp +++ b/src/webengine/api/qquickwebenginefaviconprovider.cpp @@ -152,7 +152,7 @@ QQuickWebEngineView *QQuickWebEngineFaviconProvider::viewForIconUrl(const QUrl & // latest WebEngineView which was raised an iconChanged signal. if (m_latestView) { QList<QUrl> *iconUrls = m_iconUrlMap[m_latestView]; - if (iconUrls->contains(iconUrl)) + if (iconUrls && iconUrls->contains(iconUrl)) return m_latestView; } diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 6ca9954cf..f0811014b 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -1066,8 +1066,8 @@ void QQuickWebEngineView::setTestSupport(QQuickWebEngineTestSupport *testSupport { Q_D(QQuickWebEngineView); d->m_testSupport = testSupport; + Q_EMIT testSupportChanged(); } - #endif bool QQuickWebEngineView::activeFocusOnPress() const @@ -1302,16 +1302,23 @@ bool QQuickWebEngineView::recentlyAudible() const void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { +#if defined(ENABLE_PDF) Q_D(const QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); d->adapter->printToPDF(pageLayout, filePath); +#else + Q_UNUSED(filePath); + Q_UNUSED(pageSizeId); + Q_UNUSED(orientation); +#endif } void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { +#if defined (ENABLE_PDF) Q_D(QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); @@ -1322,6 +1329,16 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.insert(requestId, callback); +#else + Q_UNUSED(pageSizeId); + Q_UNUSED(orientation); + + // Call back with null result. + QJSValueList args; + args.append(QJSValue(QByteArray().data())); + QJSValue callbackCopy = callback; + callbackCopy.call(args); +#endif } void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement) diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 16c4799b5..4f9e483bc 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -125,7 +125,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_PROPERTY(uint webChannelWorld READ webChannelWorld WRITE setWebChannelWorld NOTIFY webChannelWorldChanged REVISION 3) #ifdef ENABLE_QML_TESTSUPPORT_API - Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport FINAL) + Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport NOTIFY testSupportChanged FINAL) #endif Q_FLAGS(FindFlags); @@ -513,6 +513,10 @@ Q_SIGNALS: Q_REVISION(4) void fileDialogRequested(QQuickWebEngineFileDialogRequest *request); Q_REVISION(4) void formValidationMessageRequested(QQuickWebEngineFormValidationMessageRequest *request); +#ifdef ENABLE_QML_TESTSUPPORT_API + void testSupportChanged(); +#endif + protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE; diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index b111e92cd..d692140ef 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -123,9 +123,6 @@ public: virtual void didFetchDocumentInnerText(quint64, const QString&) Q_DECL_OVERRIDE { } virtual void didFindText(quint64, int) Q_DECL_OVERRIDE; virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) - virtual void didPrintPageOnPrinter(quint64, bool) Q_DECL_OVERRIDE { } -#endif virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index c5ebe0f06..615e3eed0 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -62,14 +62,14 @@ On all platforms, the following tools are required: \list - \li \l Python 2.7 or later + \li \l Python 2.7.5 or later \li Bison, Flex \li GPerf \endlist \section2 Windows - On Windows, Visual Studio 2013 or Visual Studio 2015 is required. + On Windows, Visual Studio 2015 and Windows 10 SDK are required. \section2 Linux diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 99b9c4e6f..2bbf82810 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -65,6 +65,10 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } +contains(WEBENGINE_CONFIG, enable_pdf) { + DEFINES += ENABLE_PDF +} + !build_pass { chromium_attributions.commands = \ cd $$shell_quote($$shell_path($$PWD/../3rdparty)) && \ diff --git a/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp b/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp index e47f135e8..a39c0e483 100644 --- a/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp +++ b/src/webenginewidgets/api/qtwebenginewidgetsglobal.cpp @@ -48,18 +48,26 @@ namespace QtWebEngineCore } QT_BEGIN_NAMESPACE + +#ifndef QT_NO_OPENGL +Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +#endif + static void initialize() { - //On window/ANGLE, calling QtWebEngine::initialize from DllMain will result in a crash. - //To ensure it doesn't, we check that when loading the library - //QCoreApplication is not yet instantiated, ensuring the call will be deferred -#if defined(Q_OS_WIN) - if (QCoreApplication::instance() - && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { +#ifndef QT_NO_OPENGL + if (QCoreApplication::instance()) { + //On window/ANGLE, calling QtWebEngine::initialize from DllMain will result in a crash. + if (!qt_gl_global_share_context()) { + qWarning("Qt WebEngine seems to be initialized from a plugin. Please " + "set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute " + "before constructing QGuiApplication."); + } return; } -#endif + //QCoreApplication is not yet instantiated, ensuring the call will be deferred qAddPreRoutine(QtWebEngineCore::initialize); +#endif // QT_NO_OPENGL } Q_CONSTRUCTOR_FUNCTION(initialize) diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index ca160c362..16e9438c9 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -47,6 +47,7 @@ #include "favicon_manager.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" +#include "pdfium_document_wrapper_qt.h" #include "qwebenginefullscreenrequest.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" @@ -79,6 +80,9 @@ #include <QMenu> #include <QMessageBox> #include <QMimeData> +#ifndef QT_NO_PRINTER +#include <QPrinter> +#endif #include <QStandardPaths> #include <QStyle> #include <QTimer> @@ -92,6 +96,87 @@ using namespace QtWebEngineCore; static const int MaxTooltipLength = 1024; +#ifndef QT_NO_PRINTER +#if defined(ENABLE_PDF) +static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) +{ + QRect printerPageRect = printer.pageRect(); + PdfiumDocumentWrapperQt pdfiumWrapper(data.constData(), data.size(), printerPageRect.size()); + + int toPage = printer.toPage(); + int fromPage = printer.fromPage(); + bool ascendingOrder = true; + + if (fromPage == 0 && toPage == 0) { + fromPage = 1; + toPage = pdfiumWrapper.pageCount(); + } + fromPage = qMax(1, fromPage); + toPage = qMin(pdfiumWrapper.pageCount(), toPage); + + if (printer.pageOrder() == QPrinter::LastPageFirst) { + qSwap(fromPage, toPage); + ascendingOrder = false; + } + + int pageCopies = 1; + int documentCopies = 1; + + if (!printer.supportsMultipleCopies()) + documentCopies = printer.copyCount(); + + if (printer.collateCopies()) { + pageCopies = documentCopies; + documentCopies = 1; + } + + QPainter painter; + if (!painter.begin(&printer)) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Failure to print on printer %ls: Could not open printer for painting.", qUtf16Printable(printer.printerName())); +#else + qWarning("Failure to print on printer %s: Could not open printer for painting.", qPrintable(printer.printerName())); +#endif + return false; + } + + for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { + int currentPageIndex = fromPage; + while (true) { + for (int printedPages = 0; printedPages < pageCopies; printedPages++) { + if (printer.printerState() == QPrinter::Aborted + || printer.printerState() == QPrinter::Error) + return false; + + QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1); + if (currentImage.isNull()) + return false; + + painter.drawImage(printerPageRect, currentImage, currentImage.rect()); + if (printedPages < pageCopies - 1) + printer.newPage(); + } + + if (currentPageIndex == toPage) + break; + + if (ascendingOrder) + currentPageIndex++; + else + currentPageIndex--; + + printer.newPage(); + } + if (printedDocuments < documentCopies - 1) + printer.newPage(); + } + painter.end(); + + return true; +} +#endif // defined(ENABLE_PDF) +#endif // QT_NO_PRINTER + static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { switch (disposition) { @@ -142,6 +227,9 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , fullscreenMode(false) , webChannel(nullptr) , webChannelWorldId(QWebEngineScript::MainWorld) +#ifndef QT_NO_PRINTER + , currentPrinter(nullptr) +#endif { memset(actions, 0, sizeof(actions)); } @@ -154,7 +242,16 @@ QWebEnginePagePrivate::~QWebEnginePagePrivate() RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) { - return new RenderWidgetHostViewQtDelegateWidget(client); + // Set the QWebEngineView as the parent for a popup delegate, so that the new popup window + // responds properly to clicks in case the QWebEngineView is inside a modal QDialog. Setting the + // parent essentially notifies the OS that the popup window is part of the modal session, and + // should allow interaction. + // The new delegate will not be deleted by the parent view though, because we unset the parent + // when the parent is destroyed. The delegate will be destroyed by Chromium when the popup is + // dismissed. + // If the delegate is not for a popup, but for a newly created QWebEngineView, the parent is 0 + // just like before. + return new RenderWidgetHostViewQtDelegateWidget(client, this->view); } void QWebEnginePagePrivate::titleChanged(const QString &title) @@ -380,15 +477,27 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) { - m_callbacks.invoke(requestId, result); -} - +#if defined(ENABLE_PDF) #ifndef QT_NO_PRINTER -void QWebEnginePagePrivate::didPrintPageOnPrinter(quint64 requestId, bool result) -{ + // If no currentPrinter is set that means that were printing to PDF only. + if (!currentPrinter) { + m_callbacks.invoke(requestId, result); + return; + } + + bool printerResult = printPdfDataOnPrinter(result, *currentPrinter); + + m_callbacks.invoke(requestId, printerResult); + currentPrinter = nullptr; +#else // If print support is disabled, only PDF printing is available. m_callbacks.invoke(requestId, result); +#endif // ifndef QT_NO_PRINTER +#else // defined(ENABLE_PDF) + // we should never enter this branch, but just for safe-keeping... + Q_UNUSED(result); + m_callbacks.invoke(requestId, QByteArray()); +#endif // defined(ENABLE_PDF) } -#endif void QWebEnginePagePrivate::passOnFocus(bool reverse) { @@ -1835,8 +1944,23 @@ QSizeF QWebEnginePage::contentsSize() const */ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout) { +#if defined(ENABLE_PDF) Q_D(const QWebEnginePage); +#ifndef QT_NO_PRINTER + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); +#endif + return; + } +#endif d->adapter->printToPDF(pageLayout, filePath); +#else + Q_UNUSED(filePath); + Q_UNUSED(pageLayout); +#endif // if defined(ENABLE_PDF) } @@ -1854,8 +1978,24 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout) { Q_D(QWebEnginePage); +#if defined(ENABLE_PDF) +#ifndef QT_NO_PRINTER + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); +#endif + d->m_callbacks.invokeEmpty(resultCallback); + return; + } +#endif // ifndef QT_NO_PRINTER quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.registerCallback(requestId, resultCallback); +#else // if defined(ENABLE_PDF) + Q_UNUSED(pageLayout); + d->m_callbacks.invokeEmpty(resultCallback); +#endif // if defined(ENABLE_PDF) } #ifndef QT_NO_PRINTER @@ -1875,8 +2015,23 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); - quint64 requestId = d->adapter->printOnPrinterCallbackResult(printer); +#if defined(ENABLE_PDF) + if (d->currentPrinter) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + qWarning("Cannot print page on printer %ls: Already printing on %ls.", qUtf16Printable(printer->printerName()), qUtf16Printable(d->currentPrinter->printerName())); +#else + qWarning("Cannot print page on printer %s: Already printing on %s.", qPrintable(printer->printerName()), qPrintable(d->currentPrinter->printerName())); +#endif + d->m_callbacks.invokeDirectly(resultCallback, false); + return; + } + d->currentPrinter = printer; + quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(), printer->colorMode() == QPrinter::Color); d->m_callbacks.registerCallback(requestId, resultCallback); +#else // if defined(ENABLE_PDF) + Q_UNUSED(printer); + d->m_callbacks.invokeDirectly(resultCallback, false); +#endif // if defined(ENABLE_PDF) } #endif // QT_NO_PRINTER diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 8d78429d8..0ad077a0e 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -119,9 +119,6 @@ public: virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFindText(quint64 requestId, int matchCount) Q_DECL_OVERRIDE; virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; -#ifndef QT_NO_PRINTER - virtual void didPrintPageOnPrinter(quint64 requestId, bool result) Q_DECL_OVERRIDE; -#endif virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; @@ -181,6 +178,9 @@ public: mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; +#ifndef QT_NO_PRINTER + QPrinter *currentPrinter; +#endif // QT_NO_PRINTER }; QT_END_NAMESPACE 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 eb3a3931a..27268d26b 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -138,6 +138,21 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_AlwaysShowToolTips); + + if (parent) { + // Unset the popup parent if the parent is being destroyed, thus making sure a double + // delete does not happen. + // Also in case the delegate is destroyed before its parent (when a popup is simply + // dismissed), this connection will automatically be removed by ~QObject(), preventing + // a use-after-free. + connect(parent, &QObject::destroyed, + this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete); + } +} + +void RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete() +{ + setParent(Q_NULLPTR); } void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient* container) @@ -164,7 +179,11 @@ void RenderWidgetHostViewQtDelegateWidget::initAsPopup(const QRect& screenRect) // to be destroyed. setAttribute(Qt::WA_ShowWithoutActivating); setFocusPolicy(Qt::NoFocus); - setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); + + // macOS doesn't like Qt::ToolTip when QWebEngineView is inside a modal dialog, specifically by + // not forwarding click events to the popup. So we use Qt::Tool which behaves the same way, but + // works on macOS too. + setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); setGeometry(screenRect); show(); @@ -183,6 +202,13 @@ QRectF RenderWidgetHostViewQtDelegateWidget::contentsRect() const void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus() { + // If the corresponding window is inactive (for example, because of a popup), + // the active focus cannot be set. Sync up with the Window System to try to + // reactivate the window in time if the other window (possibly popup) which took + // the focus is already closed. + if (window() && !window()->isActive()) + QGuiApplication::sync(); + m_rootItem->forceActiveFocus(); } diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h index 77907ec5a..68e6a176b 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -87,6 +87,7 @@ protected: private slots: void onWindowPosChanged(); + void removeParentBeforeParentDelete(); private: RenderWidgetHostViewQtDelegateClient *m_client; diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro index 64e475422..b60de6e1e 100644 --- a/src/webenginewidgets/webenginewidgets.pro +++ b/src/webenginewidgets/webenginewidgets.pro @@ -52,4 +52,11 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } +contains(WEBENGINE_CONFIG, enable_pdf) { + DEFINES += ENABLE_PDF +} + +qtHaveModule(printsupport) { + QT += printsupport +} load(qt_module) |