diff options
158 files changed, 4992 insertions, 1429 deletions
diff --git a/.qmake.conf b/.qmake.conf index 9bdf7cc2a..a988f0fac 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -7,4 +7,4 @@ QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD) load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.8.1 +MODULE_VERSION = 5.9.0 diff --git a/configure.json b/configure.json index 22870a0eb..ad9fd117c 100644 --- a/configure.json +++ b/configure.json @@ -1,14 +1,24 @@ { "module": "webengine", + "depends": [ + "printsupport" + ], "testDir": "tools/qmake/config.tests", "commandline": { "options": { "alsa": "boolean", + "embedded": "boolean", + "ffmpeg": { "type": "enum", "name": "system-ffmpeg", "values": { "system": "yes", "qt": "no" } }, + "opus": { "type": "enum", "name": "system-opus", "values": { "system": "yes", "qt": "no" } }, + "webp": { "type": "enum", "name": "system-webp", "values": { "system": "yes", "qt": "no" } }, + "pepper-plugins": "boolean", + "printing-and-pdf": "boolean", "proprietary-codecs": "boolean", "pulseaudio": "boolean", - "spellchecker": "boolean" + "spellchecker": "boolean", + "webrtc": "boolean" } }, @@ -25,10 +35,50 @@ "sources": [ { "type": "pkgConfig", "args": "libpulse >= 0.9.10 libpulse-mainloop-glib" } ] + }, + "ffmpeg": { + "label": "libavcodec libavformat libavutil", + "sources": [ + { "type": "pkgConfig", "args": "libavcodec libavformat libavutil" } + ] + }, + "opus": { + "label": "opus", + "sources": [ + { "type": "pkgConfig", "args": "opus" } + ] + }, + "webp": { + "label": "libwebp and libwebpdemux", + "sources": [ + { "type": "pkgConfig", "args": "libwebp libwebpdemux" } + ] + } + }, + + "tests" : { + "ninja": { + "label": "system ninja", + "type": "detectNinja" + }, + "gn": { + "label": "system gn", + "type": "detectGn" + }, + "embedded": { + "label": "embedded", + "type": "embedded" } }, "features": { + "embedded": { + "label": "Embedded build", + "condition": "config.unix", + "autoDetect": "tests.embedded", + "purpose": "Enables the embedded build configuration", + "output": [ "privateFeature" ] + }, "alsa": { "label": "ALSA", "condition": "config.unix && libs.alsa", @@ -40,6 +90,19 @@ "condition": "libs.pulseaudio", "output": [ "privateFeature" ] }, + "pepper-plugins": { + "label": "Pepper Plugins", + "autoDetect": "!features.embedded", + "purpose": "Enables use of Pepper Flash and Widevine plugins", + "output": [ "privateFeature" ] + }, + "printing-and-pdf": { + "label": "Printing and PDF", + "condition": "module.printsupport && features.printer", + "autoDetect": "!features.embedded", + "purpose": "Enables printing and output to PDF", + "output": [ "privateFeature" ] + }, "proprietary-codecs": { "label": "Proprietary Codecs", "autoDetect": false, @@ -50,6 +113,41 @@ "label": "Spellchecker", "purpose": "Enables the use of Chromium's spellchecker", "output": [ "privateFeature" ] + }, + "webrtc": { + "label": "WebRTC", + "autoDetect": "!features.embedded", + "purpose": "Enables WebRTC support", + "output": [ "privateFeature" ] + }, + "system-webp": { + "label": "libwebp and libwebpdemux", + "autoDetect": "config.unix", + "condition": "libs.webp", + "output": [ "privateFeature" ] + }, + "system-opus": { + "label": "Opus", + "autoDetect": "config.unix", + "condition": "libs.opus", + "output": [ "privateFeature" ] + }, + "system-ffmpeg": { + "label": "ffmpeg", + "autoDetect": false, + "condition": "libs.ffmpeg && features.system-opus && features.system-webp", + "output": [ "privateFeature" ] + }, + "system-ninja": { + "label": "Using system ninja", + "condition": "tests.ninja", + "output": [ "privateFeature" ] + }, + "system-gn": { + "label": "Using system gn", + "autoDetect": false, + "condition": "tests.gn", + "output": [ "privateFeature" ] } }, @@ -57,8 +155,13 @@ { "section": "Qt WebEngine", "entries": [ + "embedded", + "pepper-plugins", + "printing-and-pdf", "proprietary-codecs", "spellchecker", + "webrtc", + "system-ninja", { "type": "feature", "args": "alsa", @@ -68,6 +171,15 @@ "type": "feature", "args": "pulseaudio", "condition": "config.unix" + }, + { + "section": "System libraries", + "condition": "config.unix", + "entries": [ + "system-webp", + "system-opus", + "system-ffmpeg" + ] } ] } diff --git a/configure.pri b/configure.pri new file mode 100644 index 000000000..23f31686e --- /dev/null +++ b/configure.pri @@ -0,0 +1,34 @@ +equals(QMAKE_HOST.os, Windows): EXE_SUFFIX = .exe + +defineTest(qtConfTest_detectNinja) { + ninja = $$qtConfFindInPath("ninja$$EXE_SUFFIX") + !isEmpty(ninja) { + qtLog("Found ninja from path: $$ninja") + qtRunLoggedCommand("$$ninja --version", version)|return(false) + contains(version, "1.*"): return(true) + qtLog("Ninja version too old") + } + qtLog("Building own ninja") + return(false) +} + +defineTest(qtConfTest_detectGn) { + gn = $$qtConfFindInPath("gn$$EXE_SUFFIX") + !isEmpty(gn) { + qtRunLoggedCommand("$$gn --version", version)|return(false) + #accept all for now + contains(version, ".*"): return(true) + qtLog("Gn version too old") + } + qtLog("Building own gn") + return(false) +} + +defineTest(qtConfTest_embedded) { + lessThan(QT_MINOR_VERSION, 9) { + cross_compile: return(true) + return(false) + } + $$qtConfEvaluate("features.cross_compile"): return(true) + return(false) +} diff --git a/examples/webenginewidgets/demobrowser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp index e684d3757..c877e021e 100644 --- a/examples/webenginewidgets/demobrowser/tabwidget.cpp +++ b/examples/webenginewidgets/demobrowser/tabwidget.cpp @@ -97,12 +97,6 @@ TabBar::TabBar(QWidget *parent) setMovable(true); } -TabWidget::~TabWidget() -{ - delete m_fullScreenNotification; - delete m_fullScreenView; -} - void TabBar::selectTabAction() { if (QShortcut *shortCut = qobject_cast<QShortcut*>(sender())) { @@ -327,6 +321,12 @@ TabWidget::TabWidget(QWidget *parent) m_lineEdits = new QStackedWidget(this); } +TabWidget::~TabWidget() +{ + if (m_fullScreenView) + delete m_fullScreenView; +} + void TabWidget::clear() { // clear the recently closed tabs @@ -430,23 +430,23 @@ void TabWidget::fullScreenRequested(QWebEngineFullScreenRequest request) }); m_fullScreenView->addAction(exitFullScreenAction); } + m_oldWindowGeometry = window()->geometry(); + m_fullScreenView->setGeometry(m_oldWindowGeometry); webPage->setView(m_fullScreenView); request.accept(); m_fullScreenView->showFullScreen(); - m_fullScreenView->raise(); m_fullScreenNotification->show(); + window()->hide(); } else { if (!m_fullScreenView) return; WebView *oldWebView = this->webView(m_lineEdits->currentIndex()); webPage->setView(oldWebView); request.accept(); - // Change the delete and window hide/show back to a simple m_fullScreenView->hide() - // once QTBUG-46701 gets fixed. delete m_fullScreenView; m_fullScreenView = 0; - window()->hide(); window()->show(); + window()->setGeometry(m_oldWindowGeometry); } } diff --git a/examples/webenginewidgets/demobrowser/tabwidget.h b/examples/webenginewidgets/demobrowser/tabwidget.h index 77e7dde42..82dcf960d 100644 --- a/examples/webenginewidgets/demobrowser/tabwidget.h +++ b/examples/webenginewidgets/demobrowser/tabwidget.h @@ -257,6 +257,7 @@ private: QWebEngineProfile *m_profile; QWebEngineView *m_fullScreenView; FullScreenNotification *m_fullScreenNotification; + QRect m_oldWindowGeometry; }; #endif // TABWIDGET_H diff --git a/src/3rdparty b/src/3rdparty -Subproject 675c165d44ac5d39e9b37263e561dc1673f3bfa +Subproject 725c4c950b5fd0cd3d3aa1f9b8f40eadeb439c9 diff --git a/src/buildtools/buildtools.pro b/src/buildtools/buildtools.pro new file mode 100644 index 000000000..bbf8bd610 --- /dev/null +++ b/src/buildtools/buildtools.pro @@ -0,0 +1,24 @@ +TEMPLATE = subdirs + +ninja.file = ninja.pro +SUBDIRS += ninja + +use?(gn) { + gn.file = gn.pro + gn.depends = ninja + SUBDIRS += gn +} + +linux { + # configure_host.pro and configure_target.pro are phony pro files that + # extract things like compiler and linker from qmake. + # Only used on Linux as it is only important for cross-building and alternative compilers. + configure_host.file = configure_host.pro + configure_target.file = configure_target.pro + configure_target.depends = configure_host + + use?(gn) { + gn.depends += configure_target + } + SUBDIRS += configure_host configure_target +} diff --git a/src/buildtools/configure_host.pro b/src/buildtools/configure_host.pro new file mode 100644 index 000000000..217fad775 --- /dev/null +++ b/src/buildtools/configure_host.pro @@ -0,0 +1,48 @@ +# Prevent generating a makefile that attempts to create a lib +TEMPLATE = aux + +# Pick up the host toolchain +option(host_build) + +GN_TARGET_CPU = $$gnArch($$QT_ARCH) +GN_CPU = $$gnArch($$QMAKE_HOST.arch) +GN_OS = $$gnOS() + +clang: GN_CLANG = true +else: GN_CLANG = false + +# We always use the gcc_toolchain, because clang_toolchain is just +# a broken wrapper around it for Google's custom clang binaries. +GN_CONTENTS = \ +"import(\"//build/config/sysroot.gni\")" \ +"import(\"//build/toolchain/gcc_toolchain.gni\")" \ +"gcc_toolchain(\"host\") {" \ +" cc = \"$$which($$QMAKE_CC)\" " \ +" cxx = \"$$which($$QMAKE_CXX)\" " \ +" ld = \"$$which($$QMAKE_LINK)\" " \ +" ar = \"$$which(ar)\" " \ +" nm = \"$$which(nm)\" " \ +" toolchain_args = { " \ +" current_os = \"$$GN_OS\" " \ +" current_cpu = \"$$GN_CPU\" " \ +" } " \ +"}" \ +"gcc_toolchain(\"v8_snapshot\") {" \ +" cc = \"$$which($$QMAKE_CC)\" " \ +" cxx = \"$$which($$QMAKE_CXX)\" " \ +" ld = \"$$which($$QMAKE_LINK)\" " \ +" ar = \"$$which(ar)\" " \ +" nm = \"$$which(nm)\" " \ +" toolchain_args = { " \ +" current_os = \"$$GN_OS\" " \ +" current_cpu = \"$$GN_CPU\" " \ +" v8_current_cpu = \"$$GN_TARGET_CPU\" " \ +" } " \ +"}" + + + +GN_FILE = $$OUT_PWD/../toolchain/BUILD.gn +!build_pass { + write_file($$GN_FILE, GN_CONTENTS) +} diff --git a/src/buildtools/configure_target.pro b/src/buildtools/configure_target.pro new file mode 100644 index 000000000..ab30570e0 --- /dev/null +++ b/src/buildtools/configure_target.pro @@ -0,0 +1,29 @@ +# Prevent generating a makefile that attempts to create a lib +TEMPLATE = aux + +GN_CPU = $$gnArch($$QT_ARCH) +GN_OS = $$gnOS() + +clang: GN_CLANG = true +else: GN_CLANG = false + +# We always use the gcc_toolchain, because clang_toolchain is just +# a broken wrapper around it for Google's custom clang binaries. +GN_CONTENTS = \ +"gcc_toolchain(\"target\") {" \ +" cc = \"$$which($$QMAKE_CC)\" " \ +" cxx = \"$$which($$QMAKE_CXX)\" " \ +" ld = \"$$which($$QMAKE_LINK)\" " \ +" ar = \"$$which($${CROSS_COMPILE}ar)\" " \ +" nm = \"$$which($${CROSS_COMPILE}nm)\" " \ +" toolchain_args = { " \ +" current_os = \"$$GN_OS\" " \ +" current_cpu = \"$$GN_CPU\" " \ +" is_clang = $$GN_CLANG " \ +" } " \ +"}" + +GN_FILE = $$OUT_PWD/../toolchain/BUILD.gn +!build_pass { + write_file($$GN_FILE, GN_CONTENTS, append) +} diff --git a/src/buildtools/gn.pro b/src/buildtools/gn.pro new file mode 100644 index 000000000..092888e0e --- /dev/null +++ b/src/buildtools/gn.pro @@ -0,0 +1,36 @@ +TEMPLATE = aux +CONFIG += release + +option(host_build) + +defineReplace(buildGn) { + gn_args = $$1 + out = $$gnPath() + !qtConfig(system-ninja): ninja_path = "--path $$ninjaPath()" + # check if it is not already build + !exists($$out) { + mkpath($$dirname(out)) + src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT") + gn_bootstrap = $$system_path($$absolute_path(chromium/tools/gn/bootstrap/bootstrap.py, $$src_3rd_party_dir)) + gn_args = $$system_quote($$gn_args) + gn_configure = $$system_quote($$gn_bootstrap) --shadow --gn-gen-args=$$gn_args $$ninja_path + !system("cd $$system_quote($$system_path($$dirname(out))) && python $$gn_configure") { + error("GN build error!") + } + } +} + +isQtMinimum(5, 8) { + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private +} + +!qtConfig(system-gn) { + buildgn.target = build_gn + buildgn.commands = $$buildGn($$gnArgs()) + QMAKE_EXTRA_TARGETS += buildgn + + default_target.target = first + default_target.depends = buildgn + QMAKE_EXTRA_TARGETS += default_target +} diff --git a/src/buildtools/ninja.pro b/src/buildtools/ninja.pro new file mode 100644 index 000000000..c391d6e84 --- /dev/null +++ b/src/buildtools/ninja.pro @@ -0,0 +1,31 @@ +TEMPLATE = aux +CONFIG += release + +defineReplace(buildNinja) { + out = $$ninjaPath() + # check if it is not already build + !exists($$out) { + mkpath($$dirname(out)) + src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT") + ninja_configure = $$system_quote($$system_path($$absolute_path(ninja/configure.py, $$src_3rd_party_dir))) + !system("cd $$system_quote($$system_path($$dirname(out))) && python $$ninja_configure --bootstrap") { + error("NINJA build error!") + } + } +} + +isQtMinimum(5, 8) { + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private +} + +!qtConfig(system-ninja) { + buildninja.target = build_ninja + buildninja.commands = $$buildNinja() + QMAKE_EXTRA_TARGETS += buildninja + + default_target.target = first + default_target.depends = buildninja + QMAKE_EXTRA_TARGETS += default_target +} + diff --git a/src/core/access_token_store_qt.cpp b/src/core/access_token_store_qt.cpp index 5b8fe83f7..1819cd733 100644 --- a/src/core/access_token_store_qt.cpp +++ b/src/core/access_token_store_qt.cpp @@ -56,7 +56,7 @@ namespace QtWebEngineCore { -using content::AccessTokenStore; +using device::AccessTokenStore; using content::BrowserThread; AccessTokenStoreQt::AccessTokenStoreQt() diff --git a/src/core/access_token_store_qt.h b/src/core/access_token_store_qt.h index 973f304c0..ced69a2b6 100644 --- a/src/core/access_token_store_qt.h +++ b/src/core/access_token_store_qt.h @@ -41,7 +41,7 @@ #define ACCESS_TOKEN_STORE_QT_H #include "base/memory/ref_counted.h" -#include "content/public/browser/access_token_store.h" +#include "device/geolocation/access_token_store.h" #include <QtCore/qcompilerdetection.h> #include <QtCore/QFile> @@ -53,7 +53,7 @@ class URLRequestContextGetter; namespace QtWebEngineCore { -class AccessTokenStoreQt : public content::AccessTokenStore { +class AccessTokenStoreQt : public device::AccessTokenStore { public: AccessTokenStoreQt(); ~AccessTokenStoreQt(); diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 37f8885bb..cda01db40 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -35,6 +35,7 @@ HEADERS = \ qtwebenginecoreglobal_p.h \ qwebenginecookiestore.h \ qwebenginecookiestore_p.h \ + qwebenginehttprequest.h \ qwebengineurlrequestinterceptor.h \ qwebengineurlrequestinfo.h \ qwebengineurlrequestinfo_p.h \ @@ -44,6 +45,7 @@ HEADERS = \ SOURCES = \ qtwebenginecoreglobal.cpp \ qwebenginecookiestore.cpp \ + qwebenginehttprequest.cpp \ qwebengineurlrequestinfo.cpp \ qwebengineurlrequestjob.cpp \ qwebengineurlschemehandler.cpp diff --git a/src/core/api/qwebenginehttprequest.cpp b/src/core/api/qwebenginehttprequest.cpp new file mode 100644 index 000000000..b64af4466 --- /dev/null +++ b/src/core/api/qwebenginehttprequest.cpp @@ -0,0 +1,419 @@ +/**************************************************************************** +** +** 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 "qplatformdefs.h" +#include <QtCore/qshareddata.h> +#include <QtWebEngineCore/qwebenginehttprequest.h> +#include <algorithm> + +QT_BEGIN_NAMESPACE + +/*! + \class QWebEngineHttpRequest + \since 5.9 + \ingroup webengine + \inmodule QtWebEngineCore + + \brief The QWebEngineHttpRequest class holds a request to be sent with WebEngine. + + QWebEngineHttpRequest represents an HTTP request in the WebEngine networking stack. + It holds the information necessary to send a request over the network. It contains + a URL and some ancillary information that can be used to modify the request. + Both QWebEnginePage::load() and QWebEngineView::load() accept a QWebEngineHttpRequest + as a parameter. +*/ + +/*! + \enum QWebEngineHttpRequest::Method + \brief This enum type describes the method used to send the HTTP request: + + \value Get The GET method. + \value Post The POST method. +*/ + +class QWebEngineHttpRequestPrivate : public QSharedData +{ +public: + QUrl url; + QWebEngineHttpRequest::Method method; + typedef QPair<QByteArray, QByteArray> HeaderPair; + typedef QVector<HeaderPair> Headers; + Headers headers; + QByteArray postData; + + inline QWebEngineHttpRequestPrivate() + { + } + + ~QWebEngineHttpRequestPrivate() + { + } + + QWebEngineHttpRequestPrivate(const QWebEngineHttpRequestPrivate &other) + : QSharedData(other) + { + method = other.method; + url = other.url; + headers = other.headers; + } + + inline bool operator==(const QWebEngineHttpRequestPrivate &other) const + { + return method == other.method + && url == other.url + && headers == other.headers; + } + + Headers::ConstIterator findHeader(const QByteArray &key) const; + Headers allHeaders() const; + QVector<QByteArray> headersKeys() const; + void setHeader(const QByteArray &key, const QByteArray &value); + void unsetHeader(const QByteArray &key); + void setAllHeaders(const Headers &list); + +private: + void setHeaderInternal(const QByteArray &key, const QByteArray &value); +}; + +/*! + Constructs a QWebEngineHttpRequest object with \a url as the URL to be + requested and \a method as the method to be used. + + \sa url(), setUrl() +*/ +QWebEngineHttpRequest::QWebEngineHttpRequest(const QUrl &url, + const QWebEngineHttpRequest::Method &method) + : d(new QWebEngineHttpRequestPrivate) +{ + d->method = method; + d->url = url; +} + +/*! + Creates a copy of \a other. +*/ +QWebEngineHttpRequest::QWebEngineHttpRequest(const QWebEngineHttpRequest &other) + : d(other.d) +{ +} + +/*! + Disposes of the QWebEngineHttpRequest object. +*/ +QWebEngineHttpRequest::~QWebEngineHttpRequest() +{ + // QSharedDataPointer auto deletes + d = 0; +} + +/*! + Returns \c true if this object is the same as \a other (that is, if they + have the same method, URL, and headers). + + \sa operator!=() +*/ +bool QWebEngineHttpRequest::operator==(const QWebEngineHttpRequest &other) const +{ + return d == other.d || *d == *other.d; +} + +/*! + \fn bool QWebEngineHttpRequest::operator!=(const QWebEngineHttpRequest &other) const + + Returns \c false if this object is not the same as \a other. + + \sa operator==() +*/ + +/*! + Creates a copy of \a other. +*/ +QWebEngineHttpRequest &QWebEngineHttpRequest::operator=(const QWebEngineHttpRequest &other) +{ + d = other.d; + return *this; +} + +/*! + \fn void QWebEngineHttpRequest::swap(QWebEngineHttpRequest &other) + + Swaps this WebEngine request with \a other. This function is very + fast and never fails. +*/ + +/*! + Constructs a QWebEngineHttpRequest to \a url that uses the POST method. + + \note \a postData may contain arbitrary strings. They are translated + to appropriate raw data. + + \sa postData, setPostData() +*/ +QWebEngineHttpRequest QWebEngineHttpRequest::postRequest(const QUrl &url, + const QMap<QString, QString> &postData) +{ + QWebEngineHttpRequest result(url); + result.setMethod(QWebEngineHttpRequest::Post); + + QString buffer; + for (QMap<QString, QString>::const_iterator it = postData.begin(); it != postData.end(); it++) { + QByteArray key = QUrl::toPercentEncoding(it.key()); + QByteArray value = QUrl::toPercentEncoding(it.value()); + + if (buffer.length() > 0) + buffer += QLatin1Char('&'); + buffer += key + QLatin1Char('=') + value; + } + result.setPostData(buffer.toLatin1()); + + result.setHeader(QByteArrayLiteral("Content-Type"), + QByteArrayLiteral("application/x-www-form-urlencoded")); + return result; +} + + +/*! + Returns the method this WebEngine request is using. + + \sa setMethod() +*/ +QWebEngineHttpRequest::Method QWebEngineHttpRequest::method() const +{ + return d->method; +} + +/*! + Sets the method this WebEngine request is using to be \a method. + + \sa method() +*/ +void QWebEngineHttpRequest::setMethod(QWebEngineHttpRequest::Method method) +{ + d->method = method; +} + +/*! + Returns the URL this WebEngine request is referring to. + + \sa setUrl() +*/ +QUrl QWebEngineHttpRequest::url() const +{ + return d->url; +} + +/*! + Sets the URL this WebEngine request is referring to be \a url. + + \sa url() +*/ +void QWebEngineHttpRequest::setUrl(const QUrl &url) +{ + d->url = url; +} + +/*! + Returns the (raw) POST data this WebEngine request contains. + + \sa setPostData() +*/ +QByteArray QWebEngineHttpRequest::postData() const +{ + return d->postData; +} + +/*! + Sets the (raw) POST data this WebEngine request contains to be \a postData. + + \sa postData() +*/ +void QWebEngineHttpRequest::setPostData(const QByteArray &postData) +{ + d->postData = postData; +} + +/*! + Returns \c true if the header \a headerName is present in this + WebEngine request. + + \sa setHeader(), header(), unsetHeader(), headers() +*/ +bool QWebEngineHttpRequest::hasHeader(const QByteArray &headerName) const +{ + return d->findHeader(headerName) != d->headers.constEnd(); +} + +/*! + Returns the header specified by \a headerName. If no such header is + present, an empty QByteArray is returned, which may be + indistinguishable from a header that is present but has no content + (use hasHeader() to find out if the header exists or not). + + Headers can be set with setHeader(). + + \sa setHeader(), hasHeader(), unsetHeader(), headers() +*/ +QByteArray QWebEngineHttpRequest::header(const QByteArray &headerName) const +{ + QWebEngineHttpRequestPrivate::Headers::ConstIterator it = + d->findHeader(headerName); + if (it != d->headers.constEnd()) + return it->second; + return QByteArray(); +} + +/*! + Returns a list of all headers that are set in this WebEngine + request. The list is in the order that the headers were set. + + \sa setHeader(), header(), hasHeader(), unsetHeader() +*/ +QVector<QByteArray> QWebEngineHttpRequest::headers() const +{ + return d->headersKeys(); +} + +/*! + Sets the header \a headerName to be of value \a headerValue. + + \note Setting the same header twice overrides the previous + setting. To accomplish the behavior of multiple HTTP headers of + the same name, you should concatenate the two values, separating + them with a comma (",") and set one single header. + + \sa header(), hasHeader(), unsetHeader(), headers() +*/ +void QWebEngineHttpRequest::setHeader(const QByteArray &headerName, const QByteArray &headerValue) +{ + d->setHeader(headerName, headerValue); +} + +/*! + Removes the header specified by \a key, if present. + + \sa setHeader(), header(), hasHeader(), headers() +*/ +void QWebEngineHttpRequest::unsetHeader(const QByteArray &key) +{ + d->setHeader(key, QByteArray()); +} + +QWebEngineHttpRequestPrivate::Headers::ConstIterator +QWebEngineHttpRequestPrivate::findHeader(const QByteArray &key) const +{ + Headers::ConstIterator it = headers.constBegin(); + Headers::ConstIterator end = headers.constEnd(); + for ( ; it != end; ++it) + if (qstricmp(it->first.constData(), key.constData()) == 0) + return it; + + return end; // not found +} + +QWebEngineHttpRequestPrivate::Headers QWebEngineHttpRequestPrivate::allHeaders() const +{ + return headers; +} + +QVector<QByteArray> QWebEngineHttpRequestPrivate::headersKeys() const +{ + QVector<QByteArray> result; + result.reserve(headers.size()); + Headers::ConstIterator it = headers.constBegin(), + end = headers.constEnd(); + for ( ; it != end; ++it) + result << it->first; + + return result; +} + +/*! + \internal + Sets the header specified by \a key to \a value. +*/ +void QWebEngineHttpRequestPrivate::setHeader(const QByteArray &key, const QByteArray &value) +{ + if (key.isEmpty()) + // refuse to accept an empty header + return; + + setHeaderInternal(key, value); +} + +/*! + \internal + Removes the header specified by \a key, if present. +*/ +void QWebEngineHttpRequestPrivate::unsetHeader(const QByteArray &key) +{ + auto firstEqualsKey = [&key](const HeaderPair &header) { + return qstricmp(header.first.constData(), key.constData()) == 0; + }; + headers.erase(std::remove_if(headers.begin(), headers.end(), firstEqualsKey), + headers.end()); +} + +/*! + \internal + Sets the internal headers list to match \a list. +*/ +void QWebEngineHttpRequestPrivate::setAllHeaders(const Headers &list) +{ + headers = list; +} + +/*! + \internal + Sets the header specified by \a key to \a value. + \note key must not be empty. When unsure, use \a setHeader() instead. +*/ +void QWebEngineHttpRequestPrivate::setHeaderInternal(const QByteArray &key, const QByteArray &value) +{ + unsetHeader(key); + + if (value.isNull()) + return; // only wanted to erase key + + HeaderPair pair; + pair.first = key; + pair.second = value; + headers.append(pair); +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebenginehttprequest.h b/src/core/api/qwebenginehttprequest.h new file mode 100644 index 000000000..5b5948ba1 --- /dev/null +++ b/src/core/api/qwebenginehttprequest.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWEBENGINEHTTPREQUEST_H +#define QWEBENGINEHTTPREQUEST_H + +#include <QtWebEngineCore/qtwebenginecoreglobal.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qvector.h> +#include <QtCore/qmap.h> +#include <QtCore/qstring.h> +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + + +class QWebEngineHttpRequestPrivate; + +class QWEBENGINE_EXPORT QWebEngineHttpRequest +{ +public: + enum Method { + Get, + Post + }; + + explicit QWebEngineHttpRequest(const QUrl &url = QUrl(), + const QWebEngineHttpRequest::Method &method = QWebEngineHttpRequest::Get); + QWebEngineHttpRequest(const QWebEngineHttpRequest &other); + ~QWebEngineHttpRequest(); +#ifdef Q_COMPILER_RVALUE_REFS + QWebEngineHttpRequest &operator=(QWebEngineHttpRequest &&other) Q_DECL_NOTHROW { swap(other); + return *this; } +#endif + QWebEngineHttpRequest &operator=(const QWebEngineHttpRequest &other); + + static QWebEngineHttpRequest postRequest(const QUrl &url, + const QMap<QString, QString> &postData); + void swap(QWebEngineHttpRequest &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + + bool operator==(const QWebEngineHttpRequest &other) const; + inline bool operator!=(const QWebEngineHttpRequest &other) const + { return !operator==(other); } + + Method method() const; + void setMethod(QWebEngineHttpRequest::Method method); + + QUrl url() const; + void setUrl(const QUrl &url); + + QByteArray postData() const; + void setPostData(const QByteArray &postData); + + bool hasHeader(const QByteArray &headerName) const; + QVector<QByteArray> headers() const; + QByteArray header(const QByteArray &headerName) const; + void setHeader(const QByteArray &headerName, const QByteArray &value); + void unsetHeader(const QByteArray &headerName); + +private: + QSharedDataPointer<QWebEngineHttpRequestPrivate> d; + friend class QWebEngineHttpRequestPrivate; +}; + +Q_DECLARE_SHARED(QWebEngineHttpRequest) + +QT_END_NAMESPACE + +#endif diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 30e6efc2e..ac4649d3d 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -173,9 +173,9 @@ void BrowserAccessibilityQt::setText(QAccessible::Text t, const QString &text) QRect BrowserAccessibilityQt::rect() const { - if (!manager()) // needed implicitly by GetGlobalBoundsRect() + if (!manager()) // needed implicitly by GetScreenBoundsRect() return QRect(); - gfx::Rect bounds = GetGlobalBoundsRect(); + gfx::Rect bounds = GetScreenBoundsRect(); return QRect(bounds.x(), bounds.y(), bounds.width(), bounds.height()); } @@ -573,7 +573,7 @@ void BrowserAccessibilityQt::scrollToSubstring(int startIndex, int endIndex) { int count = characterCount(); if (startIndex < endIndex && endIndex < count) - manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange(startIndex, endIndex - startIndex)); + manager()->ScrollToMakeVisible(*this, GetPageBoundsForRange(startIndex, endIndex - startIndex)); } QVariant BrowserAccessibilityQt::currentValue() const diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index 3396f73ef..863731ff4 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -101,6 +101,7 @@ BrowserContextAdapter::BrowserContextAdapter(const QString &storageName) BrowserContextAdapter::~BrowserContextAdapter() { + m_browserContext->ShutdownStoragePartitions(); if (m_downloadManagerDelegate) content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take()); BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data()); diff --git a/src/core/browser_context_adapter_client.cpp b/src/core/browser_context_adapter_client.cpp new file mode 100644 index 000000000..3a7447686 --- /dev/null +++ b/src/core/browser_context_adapter_client.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "browser_context_adapter_client.h" +#include "content/public/browser/download_item.h" +#include "content/public/browser/save_page_type.h" + +#include <QCoreApplication> +#include <QString> + +namespace QtWebEngineCore { + +ASSERT_ENUMS_MATCH(content::DownloadItem::IN_PROGRESS, BrowserContextAdapterClient::DownloadInProgress) +ASSERT_ENUMS_MATCH(content::DownloadItem::COMPLETE, BrowserContextAdapterClient::DownloadCompleted) +ASSERT_ENUMS_MATCH(content::DownloadItem::CANCELLED, BrowserContextAdapterClient::DownloadCancelled) +ASSERT_ENUMS_MATCH(content::DownloadItem::INTERRUPTED, BrowserContextAdapterClient::DownloadInterrupted) + +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_UNKNOWN, BrowserContextAdapterClient::UnknownSavePageFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_ONLY_HTML, BrowserContextAdapterClient::SingleHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, BrowserContextAdapterClient::CompleteHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_MHTML, BrowserContextAdapterClient::MimeHtmlSaveFormat) + +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NONE, BrowserContextAdapterClient::NoReason) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, BrowserContextAdapterClient::FileFailed) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, BrowserContextAdapterClient::FileAccessDenied) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, BrowserContextAdapterClient::FileNoSpace) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG, BrowserContextAdapterClient::FileNameTooLong) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE, BrowserContextAdapterClient::FileTooLarge) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED, BrowserContextAdapterClient::FileVirusInfected) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, BrowserContextAdapterClient::FileTransientError) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED, BrowserContextAdapterClient::FileBlocked) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED, BrowserContextAdapterClient::FileSecurityCheckFailed) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT, BrowserContextAdapterClient::FileTooShort) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH, BrowserContextAdapterClient::FileHashMismatch) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, BrowserContextAdapterClient::NetworkFailed) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, BrowserContextAdapterClient::NetworkTimeout) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, BrowserContextAdapterClient::NetworkDisconnected) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN, BrowserContextAdapterClient::NetworkServerDown) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, BrowserContextAdapterClient::NetworkInvalidRequest) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, BrowserContextAdapterClient::ServerFailed) +//ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE, BrowserContextAdapterClient::ServerNoRange) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, BrowserContextAdapterClient::ServerBadContent) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED, BrowserContextAdapterClient::ServerUnauthorized) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM, BrowserContextAdapterClient::ServerCertProblem) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN, BrowserContextAdapterClient::ServerForbidden) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE, BrowserContextAdapterClient::ServerUnreachable) +ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED, BrowserContextAdapterClient::UserCanceled) +//ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN, BrowserContextAdapterClient::UserShutdown) +//ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_CRASH, BrowserContextAdapterClient::Crash) + +QString BrowserContextAdapterClient::downloadInterruptReasonToString(DownloadInterruptReason reason) +{ + switch (reason) { + default: + // Yield an error in debug mode, but fall through to some defined behavior + Q_UNREACHABLE(); + case NoReason: + return QCoreApplication::translate("DownloadInterruptReason", + "Unknown reason or not interrupted"); + case FileFailed: + return QCoreApplication::translate("DownloadInterruptReason", + "General file operation failure"); + case FileAccessDenied: + return QCoreApplication::translate("DownloadInterruptReason", + "The file cannot be written locally, due to access restrictions"); + case FileNoSpace: + return QCoreApplication::translate("DownloadInterruptReason", + "Insufficient space on the target drive"); + case FileNameTooLong: + return QCoreApplication::translate("DownloadInterruptReason", + "The directory or file name is too long"); + case FileTooLarge: + return QCoreApplication::translate("DownloadInterruptReason", + "The file size exceeds the file system limitation"); + case FileVirusInfected: + return QCoreApplication::translate("DownloadInterruptReason", + "The file is infected with a virus"); + case FileTransientError: + return QCoreApplication::translate("DownloadInterruptReason", + "Temporary problem (for example file in use, or too many open files)"); + case FileBlocked: + return QCoreApplication::translate("DownloadInterruptReason", + "The file was blocked due to local policy"); + case FileSecurityCheckFailed: + return QCoreApplication::translate("DownloadInterruptReason", + "Checking the safety of the download failed due to unexpected reasons"); + case FileTooShort: + return QCoreApplication::translate("DownloadInterruptReason", + "File seek past the end of a file (resuming previously interrupted download)"); + case FileHashMismatch: + return QCoreApplication::translate("DownloadInterruptReason", + "The partial file did not match the expected hash"); + case NetworkFailed: + return QCoreApplication::translate("DownloadInterruptReason", + "General network failure"); + case NetworkTimeout: + return QCoreApplication::translate("DownloadInterruptReason", + "The network operation has timed out"); + case NetworkDisconnected: + return QCoreApplication::translate("DownloadInterruptReason", + "The network connection has been terminated"); + case NetworkServerDown: + return QCoreApplication::translate("DownloadInterruptReason", + "The server has gone down"); + case NetworkInvalidRequest: + return QCoreApplication::translate("DownloadInterruptReason", + "The network request was invalid (for example, the URL or scheme is invalid)"); + case ServerFailed: + return QCoreApplication::translate("DownloadInterruptReason", + "General server failure"); + //case ServerNoRange: + // return QCoreApplication::translate("DownloadInterruptReason", + // "Server does not support range requests"); + case ServerBadContent: + return QCoreApplication::translate("DownloadInterruptReason", + "The server does not have the requested data"); + case ServerUnauthorized: + return QCoreApplication::translate("DownloadInterruptReason", + "The server did not authorize access to the resource"); + case ServerCertProblem: + return QCoreApplication::translate("DownloadInterruptReason", + "A problem with the server certificate occurred"); + case ServerForbidden: + return QCoreApplication::translate("DownloadInterruptReason", + "Access forbidden by the server"); + case ServerUnreachable: + return QCoreApplication::translate("DownloadInterruptReason", + "Unexpected server response"); + case UserCanceled: + return QCoreApplication::translate("DownloadInterruptReason", + "Download canceled by the user"); + //case UserShutdown: + // return QCoreApplication::translate("DownloadInterruptReason", + // "The user shut down the browser"); + //case Crash: + // return QCoreApplication::translate("DownloadInterruptReason", + // "The browser crashed"); + } +} + +} // namespace QtWebEngineCore diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h index faba08591..e1fd02f96 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/browser_context_adapter_client.h @@ -76,6 +76,37 @@ public: SavePage }; + // Keep in sync with content::DownloadInterruptReason + enum DownloadInterruptReason { + NoReason = 0, + FileFailed = 1, + FileAccessDenied = 2, + FileNoSpace = 3, + FileNameTooLong = 5, + FileTooLarge = 6, + FileVirusInfected = 7, + FileTransientError = 10, + FileBlocked = 11, + FileSecurityCheckFailed = 12, + FileTooShort = 13, + FileHashMismatch = 14, + NetworkFailed = 20, + NetworkTimeout = 21, + NetworkDisconnected = 22, + NetworkServerDown = 23, + NetworkInvalidRequest = 24, + ServerFailed = 30, + //ServerNoRange = 31, + ServerBadContent = 33, + ServerUnauthorized = 34, + ServerCertProblem = 35, + ServerForbidden = 36, + ServerUnreachable = 37, + UserCanceled = 40, + //UserShutdown = 41, + //Crash = 50 + }; + struct DownloadItemInfo { const quint32 id; const QUrl url; @@ -88,12 +119,14 @@ public: int savePageFormat; bool accepted; int downloadType; + int downloadInterruptReason; }; virtual ~BrowserContextAdapterClient() { } virtual void downloadRequested(DownloadItemInfo &info) = 0; virtual void downloadUpdated(const DownloadItemInfo &info) = 0; + static QString downloadInterruptReasonToString(DownloadInterruptReason reason); }; } // namespace diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index ca65552be..96d3fa861 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -72,8 +72,6 @@ public: base::FilePath GetCachePath() const; virtual bool IsOffTheRecord() const Q_DECL_OVERRIDE; - net::URLRequestContextGetter *GetRequestContext(); - virtual net::URLRequestContextGetter *CreateMediaRequestContext() Q_DECL_OVERRIDE; virtual net::URLRequestContextGetter *CreateMediaRequestContextForStoragePartition(const base::FilePath& partition_path, bool in_memory) Q_DECL_OVERRIDE; @@ -97,6 +95,7 @@ public: // Profile implementation: PrefService* GetPrefs() override; const PrefService* GetPrefs() const override; + net::URLRequestContextGetter *GetRequestContext() override; BrowserContextAdapter *adapter() { return m_adapter; } diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index 18835a5c7..a681de859 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -71,7 +71,7 @@ ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateErrorEnd, net::ERR_CER void CertificateErrorControllerPrivate::accept(bool accepted) { - callback.Run(accepted); + callback.Run(accepted ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY); } CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_error, @@ -80,7 +80,7 @@ CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_er content::ResourceType resource_type, bool _overridable, bool strict_enforcement, - const base::Callback<void(bool)>& cb + const base::Callback<void(content::CertificateRequestResultType)>& cb ) : certError(CertificateErrorController::CertificateError(cert_error)) , requestUrl(toQt(request_url)) diff --git a/src/core/certificate_error_controller_p.h b/src/core/certificate_error_controller_p.h index ee073b64f..abde9a7d5 100644 --- a/src/core/certificate_error_controller_p.h +++ b/src/core/certificate_error_controller_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class CertificateErrorControllerPrivate { public: - CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, content::ResourceType resource_type, bool overridable, bool strict_enforcement, const base::Callback<void(bool)>& callback); + CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, content::ResourceType resource_type, bool overridable, bool strict_enforcement, const base::Callback<void(content::CertificateRequestResultType)>& callback); void accept(bool accepted); @@ -70,7 +70,7 @@ public: CertificateErrorController::ResourceType resourceType; bool overridable; bool strictEnforcement; - const base::Callback<void(bool)> callback; + const base::Callback<void(content::CertificateRequestResultType)> callback; }; QT_END_NAMESPACE diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index d1133f5c2..1b415b9ec 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -75,13 +75,13 @@ gpu::gles2::MailboxManager *mailbox_manager() return gpuChannelManager->mailbox_manager(); } -gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox) +gpu::gles2::TextureBase* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox) { Q_UNUSED(target); return mailboxManager->ConsumeTexture(mailbox); } -unsigned int service_id(gpu::gles2::Texture *tex) +unsigned int service_id(gpu::gles2::TextureBase *tex) { return tex->service_id(); } diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h index 02fe2d3bb..9954dc1d0 100644 --- a/src/core/chromium_gpu_helper.h +++ b/src/core/chromium_gpu_helper.h @@ -52,7 +52,7 @@ struct Mailbox; class SyncPointManager; namespace gles2 { class MailboxManager; -class Texture; +class TextureBase; } } @@ -65,8 +65,8 @@ base::MessageLoop *gpu_message_loop(); gpu::SyncPointManager *sync_point_manager(); gpu::gles2::MailboxManager *mailbox_manager(); -gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox); -unsigned int service_id(gpu::gles2::Texture *tex); +gpu::gles2::TextureBase* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox); +unsigned int service_id(gpu::gles2::TextureBase *tex); #ifdef Q_OS_QNX typedef void* EGLDisplay; diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 882f5b1dd..f60b9213b 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -65,21 +65,25 @@ #include "ui/gfx/platform_font.h" #endif +#if defined(USE_OPENSSL_CERTS) +#include "net/ssl/openssl_client_key_store.h" +#endif + namespace QtWebEngineCore { -void GetScreenInfoFromNativeWindow(QWindow* window, blink::WebScreenInfo* results) +void GetScreenInfoFromNativeWindow(QWindow* window, content::ScreenInfo* results) { QScreen* screen = window->screen(); - blink::WebScreenInfo r; - r.deviceScaleFactor = screen->devicePixelRatio(); - r.depthPerComponent = 8; + content::ScreenInfo r; + r.device_scale_factor = screen->devicePixelRatio(); + r.depth_per_component = 8; r.depth = screen->depth(); - r.isMonochrome = (r.depth == 1); + r.is_monochrome = (r.depth == 1); QRect screenGeometry = screen->geometry(); - r.rect = blink::WebRect(screenGeometry.x(), screenGeometry.y(), screenGeometry.width(), screenGeometry.height()); + r.rect = gfx::Rect(screenGeometry.x(), screenGeometry.y(), screenGeometry.width(), screenGeometry.height()); QRect available = screen->availableGeometry(); - r.availableRect = blink::WebRect(available.x(), available.y(), available.width(), available.height()); + r.available_rect = gfx::Rect(available.x(), available.y(), available.width(), available.height()); *results = r; } @@ -108,14 +112,15 @@ WebContentsView* CreateWebContentsView(WebContentsImpl *web_contents, } // static -void RenderWidgetHostViewBase::GetDefaultScreenInfo(blink::WebScreenInfo* results) { +void WebContentsView::GetDefaultScreenInfo(content::ScreenInfo* results) +{ QWindow dummy; QtWebEngineCore::GetScreenInfoFromNativeWindow(&dummy, results); } } // namespace content -#if defined(USE_AURA) && !defined(USE_OZONE) +#if defined(USE_AURA) || defined(USE_OZONE) namespace content { // content/common/font_list.h @@ -123,22 +128,25 @@ std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() { std::unique_ptr<base::ListValue> font_list(new base::ListValue); - QFontDatabase database; - for (auto family : database.families()){ - base::ListValue* font_item = new base::ListValue(); - font_item->Append(new base::StringValue(family.toStdString())); - font_item->Append(new base::StringValue(family.toStdString())); // should be localized name. - // TODO: Support localized family names. - font_list->Append(font_item); - } + QFontDatabase database; + for (auto family : database.families()){ + std::unique_ptr<base::ListValue> font_item(new base::ListValue()); + font_item->AppendString(family.toStdString()); + font_item->AppendString(family.toStdString()); // localized name. + // TODO(yusukes): Support localized family names. + font_list->Append(std::move(font_item)); + } return std::move(font_list); } #if defined(ENABLE_PLUGINS) // content/browser/renderer_host/pepper/pepper_truetype_font_list.h -void GetFontFamilies_SlowBlocking(std::vector<std::string> *) +void GetFontFamilies_SlowBlocking(std::vector<std::string> *font_families) { - QT_NOT_USED + QFontDatabase database; + for (auto family : database.families()){ + font_families->push_back(family.toStdString()); + } } void GetFontsInFamily_SlowBlocking(const std::string &, std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> *) @@ -149,26 +157,14 @@ void GetFontsInFamily_SlowBlocking(const std::string &, std::vector<ppapi::proxy } // namespace content -namespace ui { - -OSExchangeData::Provider* OSExchangeData::CreateProvider() -{ - QT_NOT_USED - return 0; -} - -} // namespace ui - -#endif // defined(USE_AURA) && !defined(USE_OZONE) +#endif // defined(USE_AURA) || defined(USE_OZONE) #if defined(USE_OPENSSL_CERTS) namespace net { -class SSLPrivateKey { }; -class X509Certificate; -std::unique_ptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate) +scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate) { - return std::unique_ptr<SSLPrivateKey>(); + return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(certificate); } } // namespace net diff --git a/src/core/chromium_overrides.h b/src/core/chromium_overrides.h index b2bd398af..b27bf309c 100644 --- a/src/core/chromium_overrides.h +++ b/src/core/chromium_overrides.h @@ -40,7 +40,7 @@ #ifndef CHROMIUM_OVERRIDES_H #define CHROMIUM_OVERRIDES_H -#include "third_party/WebKit/public/platform/WebScreenInfo.h" +#include "content/public/common/screen_info.h" #include <QtGlobal> QT_BEGIN_NAMESPACE @@ -48,7 +48,7 @@ class QWindow; QT_END_NAMESPACE namespace QtWebEngineCore { -void GetScreenInfoFromNativeWindow(QWindow* window, blink::WebScreenInfo* results); +void GetScreenInfoFromNativeWindow(QWindow* window, content::ScreenInfo* results); } #endif diff --git a/src/core/config/common.pri b/src/core/config/common.pri index b5bb23684..f87eca6e5 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -1,15 +1,95 @@ # Shared configuration for all our supported platforms -# Trigger Qt-specific build conditions. -GYP_CONFIG += use_qt=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. -GYP_CONFIG += enable_web_speech=0 -# We do not use or even include the extensions -GYP_CONFIG += enable_extensions=0 - -sanitize_address: GYP_CONFIG += asan=1 -sanitize_thread: GYP_CONFIG += tsan=1 -sanitize_memory: GYP_CONFIG += msan=1 -sanitize_undefined: GYP_CONFIG += ubsan=1 +use?(gn) { + gn_args += \ + use_qt=true \ + is_component_build=false \ + is_shared=true \ + enable_media_router=false \ + enable_nacl=false \ + enable_remoting=false \ + enable_web_speech=false \ + use_experimental_allocator_shim=false \ + use_allocator=\"none\" \ + v8_use_external_startup_data=false \ + treat_warnings_as_errors=false + + use?(printing) { + gn_args += enable_basic_printing=true enable_print_preview=true + } else { + gn_args += enable_basic_printing=false enable_print_preview=false + } + + use?(pdf) { + gn_args += enable_pdf=true + } else { + gn_args += enable_pdf=false + } + + use?(pepper_plugins) { + gn_args += enable_plugins=true enable_widevine=true + } else { + gn_args += enable_plugins=false enable_widevine=false + } + + use?(spellchecker) { + gn_args += enable_spellcheck=true + } else { + gn_args += enable_spellcheck=false + } + + use?(webrtc) { + gn_args += enable_webrtc=true + } else { + gn_args += enable_webrtc=false + } + + use?(proprietary_codecs): gn_args += proprietary_codecs=true ffmpeg_branding=\"Chrome\" + + CONFIG(release, debug|release) { + force_debug_info: gn_args += symbol_level=1 + else: gn_args += symbol_level=0 + } + + !webcore_debug: gn_args += remove_webcore_debug_symbols=true + !v8base_debug: gn_args += remove_v8base_debug_symbols=true + + # Compiling with -Os makes a huge difference in binary size + contains(WEBENGINE_CONFIG, reduce_binary_size): gn_args += optimize_for_size=true + +} else { + # Trigger Qt-specific build conditions. + GYP_CONFIG += use_qt=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. + GYP_CONFIG += enable_web_speech=0 + # We do not use or even include the extensions + GYP_CONFIG += enable_extensions=0 + + sanitize_address: GYP_CONFIG += asan=1 + sanitize_thread: GYP_CONFIG += tsan=1 + sanitize_memory: GYP_CONFIG += msan=1 + sanitize_undefined: GYP_CONFIG += ubsan=1 + + use?(printing) { + GYP_CONFIG += enable_basic_printing=1 enable_print_preview=1 + } else { + GYP_CONFIG += enable_basic_printing=0 enable_print_preview=0 + } + + use?(pdf) { + GYP_CONFIG += enable_pdf=1 + } else { + GYP_CONFIG += enable_pdf=0 + } + + use?(pepper_plugins) { + GYP_CONFIG += enable_plugins=1 enable_widevine=1 + } else { + GYP_CONFIG += enable_plugins=0 enable_widevine=0 + } +} + +use?(webrtc): GYP_CONFIG += enable_webrtc=1 +else: GYP_CONFIG += enable_webrtc=0 diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 23044619b..e6b11d290 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -1,21 +1,32 @@ -GYP_ARGS += "-D qt_os=\"desktop_linux\"" - include(linux.pri) -GYP_CONFIG += \ - desktop_linux=1 \ - enable_widevine=1 \ - enable_basic_printing=1 \ - enable_print_preview=1 \ - enable_pdf=1 +use?(gn) { + gn_args += \ + use_sysroot=false \ + enable_session_service=false \ + enable_notifications=false \ + toolkit_views=false + + use?(icecc) { + gn_args += use_debug_fission=false + } + !use_gold_linker: gn_args += use_gold=false -clang { - GYP_CONFIG += werror= - clang_full_path = $$which($${QMAKE_CXX}) - # Remove the "/bin/clang++" part. - clang_prefix = $$section(clang_full_path, /, 0, -3) - GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=$${clang_prefix} - linux-clang-libc++: GYP_CONFIG += use_system_libcxx=1 } else { - GYP_CONFIG += clang=0 host_clang=0 + + GYP_ARGS += "-D qt_os=\"desktop_linux\"" + + GYP_CONFIG += \ + desktop_linux=1 + + clang { + GYP_CONFIG += werror= + clang_full_path = $$which($${QMAKE_CXX}) + # Remove the "/bin/clang++" part. + clang_prefix = $$section(clang_full_path, /, 0, -3) + GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=$${clang_prefix} + linux-clang-libc++: GYP_CONFIG += use_system_libcxx=1 + } else { + GYP_CONFIG += clang=0 host_clang=0 + } } diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri index 7a909f1e2..51d7e2671 100644 --- a/src/core/config/embedded_linux.pri +++ b/src/core/config/embedded_linux.pri @@ -2,6 +2,23 @@ GYP_ARGS += "-D qt_os=\"embedded_linux\" -I config/embedded_linux.gypi" include(linux.pri) +use?(gn) { + gn_args += \ + is_desktop_linux=false \ + use_gold=false \ + use_ozone=true \ + use_sysroot=false \ + enable_session_service=false \ + enable_notifications=false \ + ozone_auto_platforms=false \ + ozone_platform_headless=true \ + toolkit_views=false + + use?(icecc) { + gn_args += use_debug_fission=false + } +} + GYP_CONFIG += \ clang=0 \ desktop_linux=0 \ @@ -9,20 +26,15 @@ GYP_CONFIG += \ embedded=1 \ enable_autofill_dialog=0 \ enable_automation=0 \ - enable_basic_printing=0 \ enable_captive_portal_detection=0 \ enable_extensions=0 \ enable_google_now=0 \ enable_language_detection=0 \ enable_managed_users=0 \ - enable_pdf=0 \ enable_plugin_installation=0 \ - enable_plugins=0 \ - enable_print_preview=0 \ enable_session_service=0 \ enable_task_manager=0 \ enable_themes=0 \ - enable_webrtc=0 \ gtest_target_type=none \ host_clang=0 \ notifications=0 \ @@ -39,6 +51,6 @@ GYP_CONFIG += \ use_x11=0 \ v8_use_snapshot=false \ want_separate_host_toolset=1 \ - angle_enable_gl=0 \ + angle_enable_gl=0 WEBENGINE_CONFIG *= reduce_binary_size diff --git a/src/core/config/embedded_qnx.pri b/src/core/config/embedded_qnx.pri index 3effdb816..f24888776 100644 --- a/src/core/config/embedded_qnx.pri +++ b/src/core/config/embedded_qnx.pri @@ -4,9 +4,6 @@ include(common.pri) GYP_CONFIG += \ disable_nacl=1 \ - enable_basic_printing=0 \ - enable_pdf=0 \ - enable_plugins=0 \ enable_webrtc=0 \ use_ash=0 \ use_aura=1 \ diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri index b91e795ca..232cf2ddd 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -2,6 +2,98 @@ include(common.pri) include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) QT_FOR_CONFIG += gui-private webengine-private +use?(gn) { + gn_args += \ + use_cups=false \ + use_gconf=false \ + use_gio=false \ + use_gnome_keyring=false \ + use_kerberos=false \ + linux_use_bundled_binutils=false + + use?(nss) { + gn_args += \ + use_nss_certs=true \ + use_openssl_certs=false + } else { + gn_args += \ + use_nss_certs=false \ + use_openssl_certs=true + } + gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): gn_args += no_delete_null_pointer_checks=true + + clang { + clang_full_path = $$which($${QMAKE_CXX}) + # Remove the "/bin/clang++" part. + clang_prefix = $$section(clang_full_path, /, 0, -3) + gn_args += \ + is_clang=true \ + clang_use_chrome_plugins=false \ + clang_base_path=\"$${clang_prefix}\" + } else { + gn_args += \ + is_clang=false + } + + cross_compile:!host_build { + TOOLCHAIN_SYSROOT = $$[QT_SYSROOT] + !isEmpty(TOOLCHAIN_SYSROOT): gn_args += target_sysroot=\"$${TOOLCHAIN_SYSROOT}\" + } + + host_build { + gn_args += custom_toolchain=\"$$QTWEBENGINE_OUT_ROOT/src/toolchain:host\" + # Don't bother trying to use system libraries in this case + gn_args += use_glib=false + gn_args += use_system_libffi=false + } else { + gn_args += custom_toolchain=\"$$QTWEBENGINE_OUT_ROOT/src/toolchain:target\" + cross_compile { + gn_args += host_toolchain=\"$$QTWEBENGINE_OUT_ROOT/src/toolchain:host\" + gn_args += v8_snapshot_toolchain=\"$$QTWEBENGINE_OUT_ROOT/src/toolchain:v8_snapshot\" + GN_HOST_CPU = $$gnArch($$QMAKE_HOST.arch) + GN_TARGET_CPU = $$gnArch($$QT_ARCH) + gn_args += host_cpu=\"$$GN_HOST_CPU\" target_cpu=\"$$GN_TARGET_CPU\" + } + !contains(QT_CONFIG, no-pkg-config) { + # Strip '>2 /dev/null' from $$pkgConfigExecutable() + PKGCONFIG = $$first($$list($$pkgConfigExecutable())) + gn_args += pkg_config=\"$$PKGCONFIG\" + } + + qtConfig(system-zlib): use?(system_minizip): gn_args += use_system_zlib=true use_system_minizip=true + qtConfig(system-png): gn_args += use_system_libpng=true + qtConfig(system-jpeg): gn_args += use_system_libjpeg=true + use?(system_harfbuzz): gn_args += use_system_harfbuzz=true + !use?(glib): gn_args += use_glib=false + qtConfig(pulseaudio) { + gn_args += use_pulseaudio=true + } else { + gn_args += use_pulseaudio=false + } + qtConfig(alsa) { + gn_args += use_alsa=true + } else { + gn_args += use_alsa=false + } + packagesExist(libffi): gn_args += use_system_libffi=true + else: gn_args += use_system_libffi=false + !packagesExist(libpci): gn_args += use_libpci=false + !packagesExist(xscrnsaver): gn_args += use_xscrnsaver=false + + use?(system_libevent): gn_args += use_system_libevent=true + use?(system_libwebp): gn_args += use_system_libwebp=true + #use?(system_libsrtp): gn_args += use_system_libsrtp=true + use?(system_libxslt): gn_args += use_system_libxml=true use_system_libxslt=true + #use?(system_jsoncpp): gn_args += use_system_jsoncpp=true + use?(system_opus): gn_args += use_system_opus=true + use?(system_snappy): gn_args += use_system_snappy=true + use?(system_vpx): gn_args += use_system_libvpx=true + use?(system_icu): gn_args += use_system_icu=true icu_use_data_file=false + use?(system_ffmpeg): gn_args += use_system_ffmpeg=true + #use?(system_protobuf): gn_args += use_system_protobuf=true + } +} + # linux_use_bundled_gold currently relies on a hardcoded relative path from chromium/src/out/(Release|Debug) # Disable it along with the -Wl,--threads flag just in case gold isn't installed on the system. GYP_CONFIG += \ diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index 4111236ed..a9f7207e1 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -19,25 +19,44 @@ QMAKE_CLANG_PATH = $$eval(QMAKE_MAC_SDK.macx-clang.$${QMAKE_MAC_SDK}.QMAKE_CXX) QMAKE_CLANG_PATH = "$${QMAKE_CLANG_DIR}/bin/clang++" message("Using clang++ from $${QMAKE_CLANG_PATH}") system("$${QMAKE_CLANG_PATH} --version") -GYP_CONFIG += \ - qt_os=\"mac\" \ - mac_sdk_min=\"$${QMAKE_MAC_SDK_VERSION}\" \ - mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \ - 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 -# disable the API usage if the SDK version is lower. -!isMinOSXSDKVersion(10, 10, 3): GYP_CONFIG += disable_force_touch=1 - -# Pass a supported -fstack-protect flag depending on Xcode version. -lessThan(QMAKE_XCODE_VERSION, 6.3) { - GYP_CONFIG += use_xcode_stack_protector_strong=0 -} -QMAKE_MAC_SDK_PATH = "$$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path)" -exists($$QMAKE_MAC_SDK_PATH): GYP_CONFIG += mac_sdk_path=\"$${QMAKE_MAC_SDK_PATH}\" + +use?(gn) { + gn_args += \ + is_clang=true \ + use_sysroot=false \ + use_kerberos=false \ + clang_base_path=\"$${QMAKE_CLANG_DIR}\" \ + clang_use_chrome_plugins=false \ + mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \ + mac_sdk_min=\"$${QMAKE_MAC_SDK_VERSION}\" \ + toolkit_views=false \ + use_external_popup_menu=false + + use?(spellchecker) { + use?(native_spellchecker): gn_args += use_browser_spellchecker=true + else: gn_args += use_browser_spellchecker=false + } else { + macos: gn_args += use_browser_spellchecker=false + } + +} else { + GYP_CONFIG += \ + qt_os=\"mac\" \ + mac_sdk_min=\"$${QMAKE_MAC_SDK_VERSION}\" \ + mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \ + make_clang_dir=\"$${QMAKE_CLANG_DIR}\" \ + clang_use_chrome_plugins=0 + + # Force touch API is used in 49-based Chromium, which is included starting with 10.10.3 SDK, so we + # disable the API usage if the SDK version is lower. + !isMinOSXSDKVersion(10, 10, 3): GYP_CONFIG += disable_force_touch=1 + + # Pass a supported -fstack-protect flag depending on Xcode version. + lessThan(QMAKE_XCODE_VERSION, 6.3) { + GYP_CONFIG += use_xcode_stack_protector_strong=0 + } + + QMAKE_MAC_SDK_PATH = "$$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path)" + exists($$QMAKE_MAC_SDK_PATH): GYP_CONFIG += mac_sdk_path=\"$${QMAKE_MAC_SDK_PATH}\" +} diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index 7f87e885d..405004834 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -2,14 +2,20 @@ GYP_ARGS += "-D qt_os=\"win32\" -I config/windows.gypi" include(common.pri) +gn_args += \ + is_clang=false \ + use_sysroot=false \ + use_kerberos=true \ + enable_notifications=false \ + enable_session_service=false \ + ninja_use_custom_environment_files=false \ + is_multi_dll_chrome=false \ + win_linker_timing=true + GYP_CONFIG += \ disable_nacl=1 \ remoting=0 \ - use_ash=0 \ - enable_widevine=1 \ - enable_basic_printing=1 \ - enable_print_preview=1 \ - enable_pdf=1 + use_ash=0 # Libvpx build needs additional search path on Windows. GYP_ARGS += "-D qtwe_chromium_obj_dir=\"$$OUT_PWD/$$getConfigDir()/obj/$${getChromiumSrcDir()}\"" @@ -20,11 +26,29 @@ GYP_ARGS += "-D perl_exe=\"perl.exe\" -D bison_exe=\"bison.exe\" -D gperf_exe=\" # Gyp's parallel processing is broken on Windows GYP_ARGS += "--no-parallel" + +isDeveloperBuild() { + gn_args += \ + is_win_fastlink=true \ + use_incremental_linking=true +} else { + gn_args += \ + use_incremental_linking=false +} + qtConfig(angle) { + #FIXME: Expect LIBQTANGLE_NAME to be always set + #FIXME: Replace qt_egl_library and qt_glesv2_library into qt_angle_library + LIB_EGL=libEGL + LIB_GLESV2=libGLESv2 + !isEmpty(LIBQTANGLE_NAME) { + LIB_EGL=$$LIBQTANGLE_NAME + LIB_GLESV2=$$LIBQTANGLE_NAME + } CONFIG(release, debug|release) { - GYP_ARGS += "-D qt_egl_library=\"libEGL.lib\" -D qt_glesv2_library=\"libGLESv2.lib\"" + GYP_ARGS += "-D qt_egl_library=\"$${LIB_EGL}.lib\" -D qt_glesv2_library=\"$${LIB_GLESV2}.lib\"" } else { - GYP_ARGS += "-D qt_egl_library=\"libEGLd.lib\" -D qt_glesv2_library=\"libGLESv2d.lib\"" + GYP_ARGS += "-D qt_egl_library=\"$${LIB_EGL}d.lib\" -D qt_glesv2_library=\"$${LIB_GLESV2}d.lib\"" } GYP_ARGS += "-D qt_gl=\"angle\"" } else { @@ -66,7 +90,14 @@ msvc { } GYP_ARGS += "-G msvs_version=$$MSVS_VERSION" + gn_args += visual_studio_version=$$MSVS_VERSION + + SDK_PATH = $$(WINDOWSSDKDIR) + VS_PATH= $$(VSINSTALLDIR) + gn_args += visual_studio_path=$$shell_quote($$VS_PATH) + gn_args += windows_sdk_path=$$shell_quote($$SDK_PATH) + contains(QT_ARCH, "i386"): gn_args += target_cpu=\"x86\" isBuildingOnWin32(): GYP_ARGS += "-D windows_sdk_path=\"C:/Program Files/Windows Kits/10\"" } else { diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 787586540..f031da904 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -51,7 +51,6 @@ #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/public/browser/browser_main_parts.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/geolocation_delegate.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/media_observer.h" #include "content/public/browser/quota_permission_context.h" @@ -63,6 +62,8 @@ #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/public/common/url_constants.h" +#include "device/geolocation/geolocation_delegate.h" +#include "device/geolocation/geolocation_provider.h" #include "ui/base/ui_base_switches.h" #include "ui/display/screen.h" #include "ui/gl/gl_context.h" @@ -80,6 +81,8 @@ #include "dev_tools_http_handler_delegate_qt.h" #ifdef QT_USE_POSITIONING #include "location_provider_qt.h" +#else +#include "device/geolocation/location_provider.h" #endif #include "media_capture_devices_dispatcher.h" #if defined(ENABLE_BASIC_PRINTING) @@ -230,7 +233,29 @@ std::unique_ptr<base::MessagePump> messagePumpFactory() return base::WrapUnique(new MessagePumpForUIQt); } -} // namespace +// A provider of services needed by Geolocation. +class GeolocationDelegateQt : public device::GeolocationDelegate { +public: + GeolocationDelegateQt() {} + scoped_refptr<device::AccessTokenStore> CreateAccessTokenStore() final + { + return scoped_refptr<device::AccessTokenStore>(new AccessTokenStoreQt); + } + + std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() final + { +#ifdef QT_USE_POSITIONING + return base::WrapUnique(new LocationProviderQt); +#else + return nullptr; +#endif + } + +private: + DISALLOW_COPY_AND_ASSIGN(GeolocationDelegateQt); +}; + +} // anonymous namespace class BrowserMainPartsQt : public content::BrowserMainParts { @@ -246,6 +271,7 @@ public: void PreMainMessageLoopRun() Q_DECL_OVERRIDE { + device::GeolocationProvider::SetGeolocationDelegate(new GeolocationDelegateQt()); } void PostMainMessageLoopRun() @@ -386,7 +412,7 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* // SpellCheckMessageFilter is required for both Hunspell and Native configurations. host->AddFilter(new SpellCheckMessageFilter(id)); #endif -#if defined(Q_OS_MACOS) && defined(USE_BROWSER_SPELLCHECKER) +#if defined(Q_OS_MACOS) && defined(ENABLE_SPELLCHECK) && defined(USE_BROWSER_SPELLCHECKER) host->AddFilter(new SpellCheckMessageFilterPlatform(id)); #endif #if defined(ENABLE_BASIC_PRINTING) @@ -418,49 +444,11 @@ void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, c static_cast<WebContentsDelegateQt*>(webContents->GetDelegate())->overrideWebPreferences(webContents, web_prefs); } -namespace { - -// A provider of services needed by Geolocation. -class GeolocationDelegateQt : public content::GeolocationDelegate { -public: - GeolocationDelegateQt() {} - content::AccessTokenStore* CreateAccessTokenStore() final - { - return new AccessTokenStoreQt; - } - - content::LocationProvider* OverrideSystemLocationProvider() final - { -#ifdef QT_USE_POSITIONING - if (!m_location_provider) - m_location_provider = base::WrapUnique(new LocationProviderQt); - return m_location_provider.get(); -#else - return nullptr; -#endif - } - -private: -#ifdef QT_USE_POSITIONING - std::unique_ptr<LocationProviderQt> m_location_provider; -#endif - - DISALLOW_COPY_AND_ASSIGN(GeolocationDelegateQt); -}; - -} // anonymous namespace - -content::GeolocationDelegate *ContentBrowserClientQt::CreateGeolocationDelegate() -{ - return new GeolocationDelegateQt; -} - content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionContext() { return new QuotaPermissionContextQt; } - void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webContents, int cert_error, const net::SSLInfo& ssl_info, @@ -469,17 +457,12 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont bool overridable, bool strict_enforcement, bool expired_previous_decision, - const base::Callback<void(bool)>& callback, - content::CertificateRequestResultType* result) + const base::Callback<void(content::CertificateRequestResultType)>& callback) { WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); QSharedPointer<CertificateErrorController> errorController(new CertificateErrorController(new CertificateErrorControllerPrivate(cert_error, ssl_info, request_url, resource_type, overridable, strict_enforcement, callback))); contentsDelegate->allowCertificateError(errorController); - - // If we don't give the user a chance to allow it, we can reject it right away. - if (result && (!overridable || strict_enforcement)) - *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY; } void ContentBrowserClientQt::SelectClientCertificate(content::WebContents * /*webContents*/, diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index a13d14ff2..b20175439 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -87,7 +87,6 @@ public: virtual void ResourceDispatcherHostCreated() Q_DECL_OVERRIDE; virtual gl::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE; virtual content::MediaObserver* GetMediaObserver() Q_DECL_OVERRIDE; - virtual content::GeolocationDelegate* CreateGeolocationDelegate() Q_DECL_OVERRIDE; virtual content::QuotaPermissionContext *CreateQuotaPermissionContext() Q_DECL_OVERRIDE; virtual void OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) Q_DECL_OVERRIDE; virtual void AllowCertificateError(content::WebContents* web_contents, @@ -98,8 +97,7 @@ public: bool overridable, bool strict_enforcement, bool expired_previous_decision, - const base::Callback<void(bool)>& callback, - content::CertificateRequestResultType* result) Q_DECL_OVERRIDE; + const base::Callback<void(content::CertificateRequestResultType)>& callback) Q_DECL_OVERRIDE; virtual void SelectClientCertificate(content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, std::unique_ptr<content::ClientCertificateDelegate> delegate) Q_DECL_OVERRIDE; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index 84f767ee3..fa55597d1 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -48,7 +48,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_paths.h" #include "ui/base/resource/resource_bundle.h" -#include "grit/net_resources.h" +#include "net/grit/net_resources.h" #include "net/base/net_module.h" #include "content_client_qt.h" diff --git a/src/core/cookie_monster_delegate_qt.cpp b/src/core/cookie_monster_delegate_qt.cpp index 4e52f562a..d2a3377a4 100644 --- a/src/core/cookie_monster_delegate_qt.cpp +++ b/src/core/cookie_monster_delegate_qt.cpp @@ -217,7 +217,7 @@ bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByt return true; } -void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) +void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, net::CookieStore::ChangeCause cause) { if (!m_client) return; diff --git a/src/core/cookie_monster_delegate_qt.h b/src/core/cookie_monster_delegate_qt.h index f47dc86df..009abdd68 100644 --- a/src/core/cookie_monster_delegate_qt.h +++ b/src/core/cookie_monster_delegate_qt.h @@ -83,7 +83,7 @@ public: void setClient(QWebEngineCookieStore *client); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url); - void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) override; + void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, net::CookieStore::ChangeCause cause) override; private: void GetAllCookiesOnIOThread(const net::CookieMonster::GetCookieListCallback& callback); diff --git a/src/core/core.pro b/src/core/core.pro index a205d39a0..a2f3c3753 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -3,39 +3,73 @@ TEMPLATE = subdirs # core_headers is a dummy module to syncqt the headers so we can # use them by later targets core_headers.file = core_headers.pro - -# core_gyp_generator.pro is a dummy .pro file that is used by qmake -# to generate our main .gyp file -core_gyp_generator.file = core_gyp_generator.pro -core_gyp_generator.depends = core_headers - -# gyp_run.pro calls gyp through gyp_qtwebengine on the qmake step, and ninja on the make step. -gyp_run.file = gyp_run.pro -gyp_run.depends = core_gyp_generator - core_api.file = api/core_api.pro -core_api.depends = gyp_run # This will take the compile output of ninja, and link+deploy the final binary. core_module.file = core_module.pro core_module.depends = core_api -SUBDIRS += core_headers \ - core_gyp_generator +# core_generator.pro is a dummy .pro file that is used by qmake +# to generate our main .gyp/BUILD.gn file +core_generator.file = core_generator.pro +core_generator.depends = core_headers -!win32 { - # gyp_configure_host.pro and gyp_configure_target.pro are phony pro files that - # extract things like compiler and linker from qmake - # Do not use them on Windows, where Qt already expects the toolchain to be - # selected through environment varibles. - gyp_configure_host.file = gyp_configure_host.pro - gyp_configure_target.file = gyp_configure_target.pro - gyp_configure_target.depends = gyp_configure_host +use?(gn) { + # core_gn_generator.pro is a dummy .pro file that is used by qmake + # to generate our main BUILD.gn file - gyp_run.depends += gyp_configure_host gyp_configure_target - SUBDIRS += gyp_configure_host gyp_configure_target -} + core_icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat + core_icu.path = $$[QT_INSTALL_DATA]/resources + core_icu.CONFIG += no_check_exist + + core_locales.files = $$OUT_PWD/$$getConfigDir()/qtwebengine_locales/*.pak + core_locales.path = $$[QT_INSTALL_TRANSLATIONS]/qtwebengine_locales + core_locales.CONFIG += no_check_exist + + core_resources.files = \ + $$OUT_PWD/$$getConfigDir()/qtwebengine_resources.pak \ + $$OUT_PWD/$$getConfigDir()/qtwebengine_resources_100p.pak \ + $$OUT_PWD/$$getConfigDir()/qtwebengine_resources_200p.pak \ + $$OUT_PWD/$$getConfigDir()/qtwebengine_devtools_resources.pak + core_resources.path = $$[QT_INSTALL_DATA]/resources + core_resources.CONFIG += no_check_exist + INSTALLS += core_resources core_locales core_icu + + gn_run.file = gn_run.pro + gn_run.depends = core_generator -SUBDIRS += gyp_run \ - core_api \ - core_module + core_api.depends = gn_run + + SUBDIRS += \ + core_headers \ + core_generator \ + gn_run \ + core_api \ + core_module +} else { + + # gyp_run.pro calls gyp through gyp_qtwebengine on the qmake step, and ninja on the make step. + gyp_run.file = gyp_run.pro + gyp_run.depends = core_generator + core_api.depends = gyp_run + + SUBDIRS += core_headers \ + core_generator + + !win32 { + # gyp_configure_host.pro and gyp_configure_target.pro are phony pro files that + # extract things like compiler and linker from qmake + # Do not use them on Windows, where Qt already expects the toolchain to be + # selected through environment varibles. + gyp_configure_host.file = gyp_configure_host.pro + gyp_configure_target.file = gyp_configure_target.pro + gyp_configure_target.depends = gyp_configure_host + + gyp_run.depends += gyp_configure_host gyp_configure_target + SUBDIRS += gyp_configure_host gyp_configure_target + } + + SUBDIRS += gyp_run \ + core_api \ + core_module +} diff --git a/src/core/core_gyp_generator.pro b/src/core/core_generator.pro index a09683ba6..c99e10ef8 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_generator.pro @@ -1,10 +1,10 @@ -# This is a dummy .pro file used to extract some aspects of the used configuration and feed them to gyp -# We want the gyp generation step to happen after all the other config steps. For that we need to prepend -# our gyp_generator.prf feature to the CONFIG variable since it is processed backwards -CONFIG = gyp_generator $$CONFIG -GYPFILE = $$OUT_PWD/core_generated.gyp -GYPINCLUDES += $$PWD/qtwebengine.gypi -GYPSRCDIR = $$PWD + +use?(gn) { + include(core_gn_config.pri) + qtConfig(debug_and_release): CONFIG += debug_and_release +} else { + include(core_gyp_config.pri) +} TEMPLATE = lib @@ -13,7 +13,15 @@ include(core_common.pri) macos { # This fixes namespace builds on macOS. Specifically namespace ambiguity issues between Qt and # Chromium forward declarations of NSString. - forward_declaration_macro = $$shell_quote(\"Q_FORWARD_DECLARE_OBJC_CLASS(name)=class name;\") + contains(WEBENGINE_CONFIG, use_gn) { + # The single quotes are present so that qmake iteration does not interpret the space as + # delimiting a new value, they are removed before writing to the GN file, and the final shell + # quoting is done by GN itself. + forward_declaration_macro = "'Q_FORWARD_DECLARE_OBJC_CLASS(name)=class name;'" + } else { + # For GYP, quoting should be done by qmake itself. + forward_declaration_macro = $$shell_quote(\"Q_FORWARD_DECLARE_OBJC_CLASS(name)=class name;\") + } } else { forward_declaration_macro = "Q_FORWARD_DECLARE_OBJC_CLASS=QT_FORWARD_DECLARE_CLASS" } @@ -22,7 +30,8 @@ macos { DEFINES += QT_NO_KEYWORDS \ QT_USE_QSTRINGBUILDER \ $$forward_declaration_macro \ - QTWEBENGINECORE_VERSION_STR=\\\"$$MODULE_VERSION\\\" \ + QTWEBENGINECORE_VERSION_STR=\"$$MODULE_VERSION\" \ + QTWEBENGINEPROCESS_NAME=\"$$QTWEBENGINEPROCESS_NAME\" \ BUILDING_CHROMIUM # Ensure that response files, generated by qtbase/mkspecs/features/moc.prf, are found by moc. @@ -31,7 +40,7 @@ RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc # Assume that we want mobile touch and low-end hardware behaviors # whenever we are cross compiling. -cross_compile: DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES +contains(WEBENGINE_CONFIG, embedded_build): DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES qtConfig(egl): CONFIG += egl @@ -45,6 +54,7 @@ SOURCES = \ browser_accessibility_manager_qt.cpp \ browser_accessibility_qt.cpp \ browser_context_adapter.cpp \ + browser_context_adapter_client.cpp \ browser_context_qt.cpp \ browser_message_filter_qt.cpp \ certificate_error_controller.cpp \ @@ -75,7 +85,6 @@ 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 \ @@ -83,15 +92,10 @@ SOURCES = \ render_view_observer_host_qt.cpp \ render_widget_host_view_qt.cpp \ renderer/content_renderer_client_qt.cpp \ - renderer/pepper/pepper_flash_renderer_host_qt.cpp \ - renderer/pepper/pepper_renderer_host_factory_qt.cpp \ renderer/render_frame_observer_qt.cpp \ renderer/render_view_observer_qt.cpp \ renderer/user_resource_controller.cpp \ renderer/web_channel_ipc_transport.cpp \ - renderer_host/pepper/pepper_flash_browser_host_qt.cpp \ - renderer_host/pepper/pepper_host_factory_qt.cpp \ - renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp \ renderer_host/resource_dispatcher_host_delegate_qt.cpp \ renderer_host/user_resource_controller_host.cpp \ renderer_host/web_channel_ipc_transport_host.cpp \ @@ -156,7 +160,6 @@ 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 \ @@ -165,15 +168,10 @@ HEADERS = \ render_widget_host_view_qt.h \ render_widget_host_view_qt_delegate.h \ renderer/content_renderer_client_qt.h \ - renderer/pepper/pepper_flash_renderer_host_qt.h \ - renderer/pepper/pepper_renderer_host_factory_qt.h \ renderer/render_frame_observer_qt.h \ renderer/render_view_observer_qt.h \ renderer/user_resource_controller.h \ renderer/web_channel_ipc_transport.h \ - renderer_host/pepper/pepper_flash_browser_host_qt.h \ - renderer_host/pepper/pepper_host_factory_qt.h \ - renderer_host/pepper/pepper_isolated_file_system_message_filter.h \ renderer_host/resource_dispatcher_host_delegate_qt.h \ renderer_host/user_resource_controller_host.h \ renderer_host/web_channel_ipc_transport_host.h \ @@ -198,6 +196,42 @@ HEADERS = \ web_engine_visited_links_manager.h \ web_event_factory.h + +use?(pdf) { + SOURCES += pdfium_document_wrapper_qt.cpp + HEADERS += pdfium_document_wrapper_qt.h +} + +use?(pepper_plugins) { + SOURCES += \ + renderer_host/pepper/pepper_flash_browser_host_qt.cpp \ + renderer_host/pepper/pepper_host_factory_qt.cpp \ + renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp \ + renderer/pepper/pepper_flash_renderer_host_qt.cpp \ + renderer/pepper/pepper_renderer_host_factory_qt.cpp + + HEADERS += \ + renderer_host/pepper/pepper_flash_browser_host_qt.h \ + renderer_host/pepper/pepper_host_factory_qt.h \ + renderer_host/pepper/pepper_isolated_file_system_message_filter.h \ + renderer/pepper/pepper_flash_renderer_host_qt.h \ + renderer/pepper/pepper_renderer_host_factory_qt.h +} + +use?(printing) { + SOURCES += \ + printing_message_filter_qt.cpp \ + print_view_manager_base_qt.cpp \ + print_view_manager_qt.cpp \ + renderer/print_web_view_helper_delegate_qt.cpp + + HEADERS += \ + printing_message_filter_qt.h \ + print_view_manager_base_qt.h \ + print_view_manager_qt.h \ + renderer/print_web_view_helper_delegate_qt.h +} + contains(QT_CONFIG, opengl) { SOURCES += \ yuv_video_node.cpp \ diff --git a/src/core/core_gn_config.pri b/src/core/core_gn_config.pri new file mode 100644 index 000000000..fb671ddb2 --- /dev/null +++ b/src/core/core_gn_config.pri @@ -0,0 +1,10 @@ +CONFIG = gn_generator $$CONFIG +GN_SRC_DIR = $$PWD +GN_FILE = $$OUT_PWD/$$getConfigDir()/BUILD.gn +GN_FIND_MOCABLES_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_find_mocables.py) +GN_RUN_BINARY_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_run_binary.py) +GN_IMPORTS = $$PWD/qtwebengine.gni +GN_INCLUDES = $$PWD/qtwebengine_sources.gni $$PWD/qtwebengine_resources.gni +GN_CREATE_PRI = true +QMAKE_INTERNAL_INCLUDED_FILES = $$GN_IMPORTS $$GN_INCLUDES $$GN_FILE + diff --git a/src/core/core_gyp_config.pri b/src/core/core_gyp_config.pri new file mode 100644 index 000000000..999d019f9 --- /dev/null +++ b/src/core/core_gyp_config.pri @@ -0,0 +1,5 @@ +CONFIG = gyp_generator $$CONFIG +GYPFILE = $$OUT_PWD/core_generated.gyp +GYPINCLUDES += $$PWD/qtwebengine.gypi +GYPSRCDIR = $$PWD + diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 65e46dcec..fecee2536 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -4,9 +4,11 @@ include(core_common.pri) # Needed to set a CFBundleIdentifier QMAKE_INFO_PLIST = Info_mac.plist -# Look for linking information produced by gyp for our target according to core_generated.gyp -!include($$OUT_PWD/$$getConfigDir()/$${TARGET}_linking.pri) { - error("Could not find the linking information that gyp should have generated.") +use?(gn): linking_pri = $$OUT_PWD/$$getConfigDir()/$${TARGET}.pri +else: linking_pri = $$OUT_PWD/$$getConfigDir()/$${TARGET}_linking.pri + +!include($$linking_pri) { + error("Could not find the linking information that gyp/gn should have generated.") } load(qt_module) @@ -17,6 +19,32 @@ api_library_path = $$OUT_PWD/api/$$getConfigDir() # Do not precompile any headers. We are only interested in the linker step. PRECOMPILED_HEADER = +use?(gn){ + isEmpty(NINJA_OBJECTS): error("Missing object files from QtWebEngineCore linking pri.") + isEmpty(NINJA_LFLAGS): error("Missing linker flags from QtWebEngineCore linking pri") + isEmpty(NINJA_ARCHIVES): error("Missing archive files from QtWebEngineCore linking pri") + isEmpty(NINJA_LIBS): error("Missing library files from QtWebEngineCore linking pri") + NINJA_OBJECTS = $$eval($$list($$NINJA_OBJECTS)) + # Do manual response file linking for macOS and Linux + + RSP_FILE = $$OUT_PWD/$$getConfigDir()/$${TARGET}.rsp + for(object, NINJA_OBJECTS): RSP_CONTENT += $$object + write_file($$RSP_FILE, RSP_CONTENT) + macos:LIBS_PRIVATE += -Wl,-filelist,$$shell_quote($$RSP_FILE) + linux:LIBS_PRIVATE += @$$RSP_FILE + # QTBUG-58710 add main rsp file on windows + win32:QMAKE_LFLAGS += @$$RSP_FILE + linux: LIBS_PRIVATE += -Wl,--start-group $$NINJA_ARCHIVES -Wl,--end-group + else: LIBS_PRIVATE += $$NINJA_ARCHIVES + LIBS_PRIVATE += $$NINJA_LIB_DIRS $$NINJA_LIBS + # GN's LFLAGS doesn't always work across all the Linux configurations we support. + # The Windows and macOS ones from GN does provide a few useful flags however + linux: QMAKE_LFLAGS += -Wl,--gc-sections -Wl,-O1 -Wl,-z,now -Wl,-z,defs + else: QMAKE_LFLAGS += $$NINJA_LFLAGS + POST_TARGETDEPS += $$NINJA_TARGETDEPS +} + + LIBS_PRIVATE += -L$$api_library_path CONFIG *= no_smart_library_merge osx { @@ -44,7 +72,12 @@ qtConfig(egl): CONFIG += egl linux:qtConfig(separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)" -REPACK_DIR = $$OUT_PWD/$$getConfigDir()/gen/repack +use?(gn) { + REPACK_DIR = $$OUT_PWD/$$getConfigDir() +} else { + REPACK_DIR = $$OUT_PWD/$$getConfigDir()/gen/repack +} + # Duplicated from resources/resources.gyp LOCALE_LIST = am ar bg bn ca cs da de el en-GB en-US es-419 es et fa fi fil fr gu he hi hr hu id it ja kn ko lt lv ml mr ms nb nl pl pt-BR pt-PT ro ru sk sl sr sv sw ta te th tr uk vi zh-CN zh-TW for(LOC, LOCALE_LIST) { @@ -96,7 +129,7 @@ icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat } } -!win32:!build_pass:debug_and_release { +!build_pass:debug_and_release { # Special GNU make target that ensures linking isn't done for both debug and release builds # at the same time. notParallel.target = .NOTPARALLEL @@ -109,4 +142,6 @@ OTHER_FILES = \ $$files(../3rdparty/chromium/*.mm, true) \ $$files(../3rdparty/chromium/*.py, true) \ $$files(../3rdparty/chromium/*.gyp, true) \ - $$files(../3rdparty/chromium/*.gypi, true) + $$files(../3rdparty/chromium/*.gypi, true) \ + $$files(../3rdparty/chromium/*.gn, true) \ + $$files(../3rdparty/chromium/*.gni, true) diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index b122a3333..03c76dd19 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -54,8 +54,9 @@ #include "type_conversion.h" #include "yuv_video_node.h" -#include "base/message_loop/message_loop.h" #include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/threading/thread_task_runner_handle.h" #include "cc/output/delegated_frame_data.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" @@ -65,6 +66,8 @@ #include "cc/quads/texture_draw_quad.h" #include "cc/quads/tile_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" +#include "cc/resources/returned_resource.h" +#include "cc/resources/transferable_resource.h" #include "content/common/host_shared_bitmap_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "ui/gl/gl_context.h" @@ -171,6 +174,260 @@ private: QSGGeometry m_geometry; }; +class DelegatedNodeTreeHandler +{ +public: + DelegatedNodeTreeHandler(QVector<QSGNode*> *sceneGraphNodes) + : m_sceneGraphNodes(sceneGraphNodes) + { + } + + virtual ~DelegatedNodeTreeHandler(){} + + virtual void setupRenderPassNode(QSGTexture *, const QRect &, QSGNode *) = 0; + virtual void setupTextureContentNode(QSGTexture *, const QRect &, QSGTexture::Filtering, + QSGTextureNode::TextureCoordinatesTransformMode, + QSGNode *) = 0; + virtual void setupTiledContentNode(QSGTexture *, const QRect &, const QRectF &, + QSGTexture::Filtering, QSGNode *) = 0; + virtual void setupSolidColorNode(const QRect &, const QColor &, QSGNode *) = 0; + virtual void setupDebugBorderNode(QSGGeometry *, QSGFlatColorMaterial *, QSGNode *) = 0; + +#ifndef QT_NO_OPENGL + virtual void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *, + const QRectF &, const QRectF &, const QSizeF &, const QSizeF &, + YUVVideoMaterial::ColorSpace, float, float, const QRectF &, + QSGNode *) = 0; +#ifdef GL_OES_EGL_image_external + virtual void setupStreamVideoNode(MailboxTexture *, const QRectF &, + const QMatrix4x4 &, QSGNode *) = 0; +#endif // GL_OES_EGL_image_external +#endif // QT_NO_OPENGL +protected: + QVector<QSGNode*> *m_sceneGraphNodes; +}; + +class DelegatedNodeTreeUpdater : public DelegatedNodeTreeHandler +{ +public: + DelegatedNodeTreeUpdater(QVector<QSGNode*> *sceneGraphNodes) + : DelegatedNodeTreeHandler(sceneGraphNodes) + , m_nodeIterator(sceneGraphNodes->begin()) + { + } + + void setupRenderPassNode(QSGTexture *layer, const QRect &rect, QSGNode *) Q_DECL_OVERRIDE + { + QSGInternalImageNode *imageNode = static_cast<QSGInternalImageNode*>(*m_nodeIterator++); + // In case of a missing render pass, set the target rects to be empty and return early. + // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes + if (!layer) { + imageNode->setTargetRect(QRect()); + imageNode->setInnerTargetRect(QRect()); + return; + } + imageNode->setTargetRect(rect); + imageNode->setInnerTargetRect(rect); + imageNode->setTexture(layer); + imageNode->update(); + } + + void setupTextureContentNode(QSGTexture *texture, const QRect &rect, + QSGTexture::Filtering filtering, + QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm, + QSGNode *) Q_DECL_OVERRIDE + { + QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); + if (textureNode->texture() != texture) + textureNode->setTexture(texture); + if (textureNode->textureCoordinatesTransform() != texCoordTransForm) + textureNode->setTextureCoordinatesTransform(texCoordTransForm); + if (textureNode->rect() != rect) + textureNode->setRect(rect); + if (textureNode->filtering() != filtering) + textureNode->setFiltering(filtering); + } + void setupTiledContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, + QSGTexture::Filtering filtering, QSGNode *) Q_DECL_OVERRIDE + { + QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); + + if (textureNode->rect() != rect) + textureNode->setRect(rect); + if (textureNode->sourceRect() != sourceRect) + textureNode->setSourceRect(sourceRect); + if (textureNode->filtering() != filtering) + textureNode->setFiltering(filtering); + if (textureNode->texture() != texture) + textureNode->setTexture(texture); + } + void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) Q_DECL_OVERRIDE + { + QSGRectangleNode *rectangleNode = static_cast<QSGRectangleNode*>(*m_nodeIterator++); + + if (rectangleNode->rect() != rect) + rectangleNode->setRect(rect); + if (rectangleNode->color() != color) + rectangleNode->setColor(color); + } + + void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material, + QSGNode *) Q_DECL_OVERRIDE + { + QSGGeometryNode *geometryNode = static_cast<QSGGeometryNode*>(*m_nodeIterator++); + + geometryNode->setGeometry(geometry); + geometryNode->setMaterial(material); + } +#ifndef QT_NO_OPENGL + void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *, + const QRectF &, const QRectF &, const QSizeF &, const QSizeF &, + YUVVideoMaterial::ColorSpace, float, float, const QRectF &, + QSGNode *) Q_DECL_OVERRIDE + { + Q_UNREACHABLE(); + } +#ifdef GL_OES_EGL_image_external + void setupStreamVideoNode(MailboxTexture *, const QRectF &, + const QMatrix4x4 &, QSGNode *) Q_DECL_OVERRIDE + { + Q_UNREACHABLE(); + } +#endif // GL_OES_EGL_image_external +#endif // QT_NO_OPENGL + +private: + QVector<QSGNode*>::iterator m_nodeIterator; +}; + +class DelegatedNodeTreeCreator : public DelegatedNodeTreeHandler +{ +public: + DelegatedNodeTreeCreator(QVector<QSGNode*> *sceneGraphNodes, + RenderWidgetHostViewQtDelegate *apiDelegate) + : DelegatedNodeTreeHandler(sceneGraphNodes) + , m_apiDelegate(apiDelegate) + { + } + + void setupRenderPassNode(QSGTexture *layer, const QRect &rect, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + // Only QSGInternalImageNode currently supports QSGLayer textures. + QSGInternalImageNode *imageNode = m_apiDelegate->createImageNode(); + layerChain->appendChildNode(imageNode); + m_sceneGraphNodes->append(imageNode); + + // In case of a missing render pass, set the target rects to be empty and return early. + // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes + if (!layer) { + imageNode->setTargetRect(QRect()); + imageNode->setInnerTargetRect(QRect()); + return; + } + + imageNode->setTargetRect(rect); + imageNode->setInnerTargetRect(rect); + imageNode->setTexture(layer); + imageNode->update(); + } + + void setupTextureContentNode(QSGTexture *texture, const QRect &rect, + QSGTexture::Filtering filtering, + QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + QSGTextureNode *textureNode = m_apiDelegate->createTextureNode(); + textureNode->setTextureCoordinatesTransform(texCoordTransForm); + textureNode->setRect(rect); + textureNode->setTexture(texture); + textureNode->setFiltering(filtering); + + layerChain->appendChildNode(textureNode); + m_sceneGraphNodes->append(textureNode); + } + + void setupTiledContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, + QSGTexture::Filtering filtering, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + QSGTextureNode *textureNode = m_apiDelegate->createTextureNode(); + textureNode->setRect(rect); + textureNode->setSourceRect(sourceRect); + textureNode->setFiltering(filtering); + textureNode->setTexture(texture); + + layerChain->appendChildNode(textureNode); + m_sceneGraphNodes->append(textureNode); + } + + void setupSolidColorNode(const QRect &rect, const QColor &color, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + QSGRectangleNode *rectangleNode = m_apiDelegate->createRectangleNode(); + rectangleNode->setRect(rect); + rectangleNode->setColor(color); + + layerChain->appendChildNode(rectangleNode); + m_sceneGraphNodes->append(rectangleNode); + } + + void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + QSGGeometryNode *geometryNode = new QSGGeometryNode; + geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial); + + geometryNode->setGeometry(geometry); + geometryNode->setMaterial(material); + + layerChain->appendChildNode(geometryNode); + m_sceneGraphNodes->append(geometryNode); + } + +#ifndef QT_NO_OPENGL + void setupYUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, + QSGTexture *aTexture, const QRectF &yaTexCoordRect, + const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, + const QSizeF &uvTexSize, YUVVideoMaterial::ColorSpace colorspace, + float rMul, float rOff, const QRectF &rect, + QSGNode *layerChain) Q_DECL_OVERRIDE + { + YUVVideoNode *videoNode = new YUVVideoNode( + yTexture, + uTexture, + vTexture, + aTexture, + yaTexCoordRect, + uvTexCoordRect, + yaTexSize, + uvTexSize, + colorspace, + rMul, + rOff); + videoNode->setRect(rect); + + layerChain->appendChildNode(videoNode); + m_sceneGraphNodes->append(videoNode); + } +#ifdef GL_OES_EGL_image_external + void setupStreamVideoNode(MailboxTexture *texture, const QRectF &rect, + const QMatrix4x4 &textureMatrix, QSGNode *layerChain) Q_DECL_OVERRIDE + { + StreamVideoNode *svideoNode = new StreamVideoNode(texture, false, ExternalTarget); + svideoNode->setRect(rect); + svideoNode->setTextureMatrix(textureMatrix); + layerChain->appendChildNode(svideoNode); + m_sceneGraphNodes->append(svideoNode); + } +#endif // GL_OES_EGL_image_external +#endif // QT_NO_OPENGL + +private: + RenderWidgetHostViewQtDelegate *m_apiDelegate; +}; + + static inline QSharedPointer<QSGLayer> findRenderPassLayer(const cc::RenderPassId &id, const QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > &list) { typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; @@ -368,7 +625,7 @@ void MailboxTexture::setTarget(GLenum target) void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager) { - gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, m_target, m_mailboxHolder.mailbox); + gpu::gles2::TextureBase *tex = ConsumeTexture(mailboxManager, m_target, m_mailboxHolder.mailbox); // The texture might already have been deleted (e.g. when navigating away from a page). if (tex) { @@ -513,7 +770,67 @@ static YUVVideoMaterial::ColorSpace toQt(cc::YUVVideoDrawQuad::ColorSpace color_ return YUVVideoMaterial::REC_601; } -void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate) +static bool areSharedQuadStatesEqual(const cc::SharedQuadState *layerState, + const cc::SharedQuadState *prevLayerState) +{ + if (layerState->is_clipped != prevLayerState->is_clipped + || layerState->clip_rect != prevLayerState->clip_rect) + return false; + if (layerState->quad_to_target_transform != prevLayerState->quad_to_target_transform) + return false; + return qFuzzyCompare(layerState->opacity, prevLayerState->opacity); +} + +// Compares if the frame data that we got from the Chromium Compositor is +// *structurally* equivalent to the one of the previous frame. +// If it is, we will just reuse and update the old nodes where necessary. +static bool areRenderPassStructuresEqual(cc::DelegatedFrameData *frameData, + cc::DelegatedFrameData *previousFrameData) +{ + if (!previousFrameData) + return false; + + if (previousFrameData->render_pass_list.size() != frameData->render_pass_list.size()) + return false; + + for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) { + cc::RenderPass *newPass = frameData->render_pass_list.at(i).get(); + cc::RenderPass *prevPass = previousFrameData->render_pass_list.at(i).get(); + + if (newPass->id != prevPass->id) + return false; + + if (newPass->quad_list.size() != prevPass->quad_list.size()) + return false; + + cc::QuadList::ConstBackToFrontIterator it = newPass->quad_list.BackToFrontBegin(); + cc::QuadList::ConstBackToFrontIterator end = newPass->quad_list.BackToFrontEnd(); + cc::QuadList::ConstBackToFrontIterator prevIt = prevPass->quad_list.BackToFrontBegin(); + cc::QuadList::ConstBackToFrontIterator prevEnd = prevPass->quad_list.BackToFrontEnd(); + for (; it != end && prevIt != prevEnd; ++it, ++prevIt) { + const cc::DrawQuad *quad = *it; + const cc::DrawQuad *prevQuad = *prevIt; + if (!areSharedQuadStatesEqual(quad->shared_quad_state, prevQuad->shared_quad_state)) + return false; + if (quad->material != prevQuad->material) + return false; +#ifndef QT_NO_OPENGL + if (quad->material == cc::DrawQuad::YUV_VIDEO_CONTENT) + return false; +#ifdef GL_OES_EGL_image_external + if (quad->material == cc::DrawQuad::STREAM_VIDEO_CONTENT) + return false; +#endif // GL_OES_EGL_image_external +#endif // QT_NO_OPENGL + + } + } + return true; +} + +void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, + cc::ReturnedResourceArray *resourcesToRelease, + RenderWidgetHostViewQtDelegate *apiDelegate) { m_chromiumCompositorData = chromiumCompositorData; cc::DelegatedFrameData* frameData = m_chromiumCompositorData->frameData.get(); @@ -524,13 +841,11 @@ 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); - setMatrix(matrix); + matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio, + 1 / m_chromiumCompositorData->frameDevicePixelRatio); + if (QSGTransformNode::matrix() != matrix) + setMatrix(matrix); - // Keep the old objects in scope to hold a ref on layers, resources and textures - // that we can re-use. Destroy the remaining objects before returning. - SGObjects previousSGObjects; - qSwap(m_sgObjects, previousSGObjects); QHash<unsigned, QSharedPointer<ResourceHolder> > resourceCandidates; qSwap(m_chromiumCompositorData->resourceHolders, resourceCandidates); @@ -547,14 +862,32 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } frameData->resource_list.clear(); + QScopedPointer<DelegatedNodeTreeHandler> nodeHandler; - // There is currently no way to know which and how quads changed since the last frame. - // We have to reconstruct the node chain with their geometries on every update. - // Intermediate render pass node chains are going to be destroyed when previousSGObjects - // goes out of scope together with any QSGLayer that could reference them. - while (QSGNode *oldChain = firstChild()) - delete oldChain; + // 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::DelegatedFrameData *previousFrameData = m_chromiumCompositorData->previousFrameData.get(); + const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData) || m_sceneGraphNodes.empty(); + m_chromiumCompositorData->previousFrameData = nullptr; + SGObjects previousSGObjects; + QVector<QSharedPointer<QSGTexture> > textureStrongRefs; + if (buildNewTree) { + // Keep the old objects in scope to hold a ref on layers, resources and textures + // that we can re-use. Destroy the remaining objects before returning. + qSwap(m_sgObjects, previousSGObjects); + // Discard the scene graph nodes from the previous frame. + while (QSGNode *oldChain = firstChild()) + delete oldChain; + m_sceneGraphNodes.clear(); + nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate)); + } else { + // Save the texture strong refs so they only go out of scope when the method returns and + // the new vector of texture strong refs has been filled. + qSwap(m_sgObjects.textureStrongRefs, textureStrongRefs); + nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes)); + } // The RenderPasses list is actually a tree where a parent RenderPass is connected // to its dependencies through a RenderPassId reference in one or more RenderPassQuads. // The list is already ordered with intermediate RenderPasses placed before their @@ -568,149 +901,165 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, QSGNode *renderPassParent = 0; if (pass != rootRenderPass) { - QSharedPointer<QSGLayer> rpLayer = findRenderPassLayer(pass->id, previousSGObjects.renderPassLayers); - if (!rpLayer) { - rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer()); - // Avoid any premature texture update since we need to wait - // for the GPU thread to produce the dependent resources first. - rpLayer->setLive(false); - } - QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); + QSharedPointer<QSGLayer> rpLayer; + if (buildNewTree) { + rpLayer = findRenderPassLayer(pass->id, previousSGObjects.renderPassLayers); + if (!rpLayer) { + rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer()); + // Avoid any premature texture update since we need to wait + // for the GPU thread to produce the dependent resources first. + rpLayer->setLive(false); + } + QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); + rpLayer->setItem(rootNode.data()); + m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, + QSharedPointer<QSGLayer> >(pass->id, rpLayer)); + m_sgObjects.renderPassRootNodes.append(rootNode); + renderPassParent = rootNode.data(); + } else + rpLayer = findRenderPassLayer(pass->id, m_sgObjects.renderPassLayers); + rpLayer->setRect(toQt(pass->output_rect)); rpLayer->setSize(toQt(pass->output_rect.size())); rpLayer->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB); - rpLayer->setItem(rootNode.data()); - m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, QSharedPointer<QSGLayer> >(pass->id, rpLayer)); - m_sgObjects.renderPassRootNodes.append(rootNode); - renderPassParent = rootNode.data(); } else renderPassParent = this; - QSGNode *renderPassChain = buildRenderPassChain(renderPassParent); - const cc::SharedQuadState *currentLayerState = 0; - QSGNode *currentLayerChain = 0; + const cc::SharedQuadState *currentLayerState = nullptr; + QSGNode *currentLayerChain = nullptr; + + QSGNode *renderPassChain = nullptr; + if (buildNewTree) + renderPassChain = buildRenderPassChain(renderPassParent); cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin(); cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd(); for (; it != end; ++it) { const cc::DrawQuad *quad = *it; - if (currentLayerState != quad->shared_quad_state) { + if (buildNewTree && currentLayerState != quad->shared_quad_state) { currentLayerState = quad->shared_quad_state; currentLayerChain = buildLayerChain(renderPassChain, currentLayerState); } switch (quad->material) { case cc::DrawQuad::RENDER_PASS: { - const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad); - QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); - // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes. - if (!layer) - continue; + const cc::RenderPassDrawQuad *renderPassQuad + = cc::RenderPassDrawQuad::MaterialCast(quad); + QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, + m_sgObjects.renderPassLayers).data(); - // Only QSGInternalImageNode currently supports QSGLayer textures. - QSGInternalImageNode *imageNode = apiDelegate->createImageNode(); - imageNode->setTargetRect(toQt(quad->rect)); - imageNode->setInnerTargetRect(toQt(quad->rect)); - imageNode->setTexture(layer); - imageNode->update(); - currentLayerChain->appendChildNode(imageNode); + nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), currentLayerChain); break; } case cc::DrawQuad::TEXTURE_CONTENT: { const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad); - ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates); - - QSGTextureNode *textureNode = apiDelegate->createTextureNode(); - textureNode->setTextureCoordinatesTransform(tquad->y_flipped ? QSGTextureNode::MirrorVertically : QSGTextureNode::NoTransform); - textureNode->setRect(toQt(quad->rect)); - textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); - textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); - currentLayerChain->appendChildNode(textureNode); + ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), + resourceCandidates); + + nodeHandler->setupTextureContentNode( + initAndHoldTexture(resource, + quad->ShouldDrawWithBlending(), + apiDelegate), + toQt(quad->rect), + resource->transferableResource().filter == GL_LINEAR + ? QSGTexture::Linear + : QSGTexture::Nearest, + tquad->y_flipped ? QSGTextureNode::MirrorVertically + : QSGTextureNode::NoTransform, + currentLayerChain); break; } case cc::DrawQuad::SOLID_COLOR: { const cc::SolidColorDrawQuad *scquad = cc::SolidColorDrawQuad::MaterialCast(quad); - QSGRectangleNode *rectangleNode = apiDelegate->createRectangleNode(); - // Qt only supports MSAA and this flag shouldn't be needed. // If we ever want to use QSGRectangleNode::setAntialiasing for this we should // try to see if we can do something similar for tile quads first. Q_UNUSED(scquad->force_anti_aliasing_off); - - rectangleNode->setRect(toQt(quad->rect)); - rectangleNode->setColor(toQt(scquad->color)); - currentLayerChain->appendChildNode(rectangleNode); + nodeHandler->setupSolidColorNode(toQt(quad->rect), toQt(scquad->color), + currentLayerChain); break; #ifndef QT_NO_OPENGL } case cc::DrawQuad::DEBUG_BORDER: { - const cc::DebugBorderDrawQuad *dbquad = cc::DebugBorderDrawQuad::MaterialCast(quad); - QSGGeometryNode *geometryNode = new QSGGeometryNode; + const cc::DebugBorderDrawQuad *dbquad + = cc::DebugBorderDrawQuad::MaterialCast(quad); - QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); + QSGGeometry *geometry + = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); geometry->setDrawingMode(GL_LINE_LOOP); geometry->setLineWidth(dbquad->width); - // QSGGeometry::updateRectGeometry would actually set the corners in the following order: - // top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross, instead - // of having a closed loop. + // QSGGeometry::updateRectGeometry would actually set the + // corners in the following order: + // top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross, + // instead of having a closed loop. const gfx::Rect &r(dbquad->rect); geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y()); geometry->vertexDataAsPoint2D()[1].set(r.x() + r.width(), r.y()); geometry->vertexDataAsPoint2D()[2].set(r.x() + r.width(), r.y() + r.height()); geometry->vertexDataAsPoint2D()[3].set(r.x(), r.y() + r.height()); - geometryNode->setGeometry(geometry); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(toQt(dbquad->color)); - geometryNode->setMaterial(material); - geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial); - currentLayerChain->appendChildNode(geometryNode); + nodeHandler->setupDebugBorderNode(geometry, material, currentLayerChain); break; #endif } case cc::DrawQuad::TILED_CONTENT: { const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad); - ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates); - - QSGTextureNode *textureNode = apiDelegate->createTextureNode(); - textureNode->setRect(toQt(quad->rect)); - textureNode->setSourceRect(toQt(tquad->tex_coord_rect)); - textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); - textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); - currentLayerChain->appendChildNode(textureNode); + ResourceHolder *resource + = findAndHoldResource(tquad->resource_id(), resourceCandidates); + nodeHandler->setupTiledContentNode( + initAndHoldTexture(resource, + quad->ShouldDrawWithBlending(), + apiDelegate), + toQt(quad->rect), toQt(tquad->tex_coord_rect), + resource->transferableResource().filter + == GL_LINEAR ? QSGTexture::Linear + : QSGTexture::Nearest, + currentLayerChain); break; #ifndef QT_NO_OPENGL } case cc::DrawQuad::YUV_VIDEO_CONTENT: { const cc::YUVVideoDrawQuad *vquad = cc::YUVVideoDrawQuad::MaterialCast(quad); - ResourceHolder *yResource = findAndHoldResource(vquad->y_plane_resource_id(), resourceCandidates); - ResourceHolder *uResource = findAndHoldResource(vquad->u_plane_resource_id(), resourceCandidates); - ResourceHolder *vResource = findAndHoldResource(vquad->v_plane_resource_id(), resourceCandidates); + ResourceHolder *yResource + = findAndHoldResource(vquad->y_plane_resource_id(), resourceCandidates); + ResourceHolder *uResource + = findAndHoldResource(vquad->u_plane_resource_id(), resourceCandidates); + ResourceHolder *vResource + = findAndHoldResource(vquad->v_plane_resource_id(), resourceCandidates); ResourceHolder *aResource = 0; - // This currently requires --enable-vp8-alpha-playback and needs a video with alpha data to be triggered. + // This currently requires --enable-vp8-alpha-playback and + // needs a video with alpha data to be triggered. if (vquad->a_plane_resource_id()) - aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceCandidates); - - YUVVideoNode *videoNode = new YUVVideoNode( - initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()), - initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()), - initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()), - aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0, - toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect), - toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), - toQt(vquad->color_space), - vquad->resource_multiplier, vquad->resource_offset); - videoNode->setRect(toQt(quad->rect)); - currentLayerChain->appendChildNode(videoNode); + aResource = findAndHoldResource(vquad->a_plane_resource_id(), + resourceCandidates); + + nodeHandler->setupYUVVideoNode( + initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()), + aResource + ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) + : 0, + toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect), + toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), + toQt(vquad->color_space), + vquad->resource_multiplier, vquad->resource_offset, + toQt(quad->rect), + currentLayerChain); break; #ifdef GL_OES_EGL_image_external } case cc::DrawQuad::STREAM_VIDEO_CONTENT: { const cc::StreamVideoDrawQuad *squad = cc::StreamVideoDrawQuad::MaterialCast(quad); - ResourceHolder *resource = findAndHoldResource(squad->resource_id(), resourceCandidates); - MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending())); - texture->setTarget(GL_TEXTURE_EXTERNAL_OES); // since this is not default TEXTURE_2D type - - StreamVideoNode *svideoNode = new StreamVideoNode(texture, false, ExternalTarget); - svideoNode->setRect(toQt(squad->rect)); - svideoNode->setTextureMatrix(toQt(squad->matrix.matrix())); - currentLayerChain->appendChildNode(svideoNode); + ResourceHolder *resource = findAndHoldResource(squad->resource_id(), + resourceCandidates); + MailboxTexture *texture + = static_cast<MailboxTexture *>( + initAndHoldTexture(resource, quad->ShouldDrawWithBlending()) + ); + // since this is not default TEXTURE_2D type + texture->setTarget(GL_TEXTURE_EXTERNAL_OES); + + nodeHandler->setupStreamVideoNode(texture, toQt(squad->rect), + toQt(squad->matrix.matrix()), currentLayerChain); break; #endif // GL_OES_EGL_image_external #endif // QT_NO_OPENGL @@ -721,9 +1070,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } } } + // Send resources of remaining candidates back to the child compositors so that + // they can be freed or reused. + typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator + ResourceHolderIterator; - // Send resources of remaining candidates back to the child compositors so that they can be freed or reused. - typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator ResourceHolderIterator; ResourceHolderIterator end = resourceCandidates.constEnd(); for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it) resourcesToRelease->push_back((*it)->returnResource()); @@ -777,7 +1128,7 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe continue; } } - gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); + gpuMessageLoop->task_runner()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); } m_mailboxesFetchedWaitCond.wait(&m_mutex); @@ -869,7 +1220,7 @@ void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTextu delete fence; } if (--frameNode->m_numPendingSyncPoints == 0) - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::fenceAndUnlockQt, frameNode)); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::fenceAndUnlockQt, frameNode)); #else Q_UNUSED(frameNode) Q_UNUSED(texture) diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index 36ec20f1d..6178bd232 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -74,6 +74,7 @@ public: ChromiumCompositorData() : frameDevicePixelRatio(1) { } QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders; std::unique_ptr<cc::DelegatedFrameData> frameData; + std::unique_ptr<cc::DelegatedFrameData> previousFrameData; qreal frameDevicePixelRatio; }; @@ -100,6 +101,7 @@ private: QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes; QVector<QSharedPointer<QSGTexture> > textureStrongRefs; } m_sgObjects; + QVector<QSGNode*> m_sceneGraphNodes; int m_numPendingSyncPoints; QWaitCondition m_mailboxesFetchedWaitCond; QMutex m_mutex; diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp index 5fd35ee29..468c5f05f 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.cpp +++ b/src/core/dev_tools_http_handler_delegate_qt.cpp @@ -53,11 +53,10 @@ #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "components/devtools_discovery/devtools_discovery_manager.h" -#include "components/devtools_discovery/devtools_target_descriptor.h" -#include "components/devtools_http_handler/devtools_http_handler.h" +#include "content/browser/devtools/devtools_http_handler.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_frontend_host.h" +#include "content/public/browser/devtools_socket_factory.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" @@ -69,30 +68,26 @@ #include "net/socket/tcp_server_socket.h" using namespace content; -using namespace devtools_discovery; -using namespace devtools_http_handler; namespace { -const char kTargetTypePage[] = "page"; -const char kTargetTypeSharedWorker[] = "worker"; -const char kTargetTypeServiceWorker[] = "service_worker"; -const char kTargetTypeOther[] = "other"; - -class TCPServerSocketFactory - : public DevToolsHttpHandler::ServerSocketFactory { +class TCPServerSocketFactory : public content::DevToolsSocketFactory { public: TCPServerSocketFactory(const std::string& address, int port, int backlog) : m_address(address), m_port(port), m_backlog(backlog) {} private: std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { - std::unique_ptr<net::ServerSocket> socket(new net::TCPServerSocket(nullptr, net::NetLog::Source())); + std::unique_ptr<net::ServerSocket> socket(new net::TCPServerSocket(nullptr, net::NetLogSource())); if (socket->ListenWithAddressAndPort(m_address, m_port, m_backlog) != net::OK) return std::unique_ptr<net::ServerSocket>(); return socket; } + std::unique_ptr<net::ServerSocket> CreateForTethering(std::string* out_name) override + { + return nullptr; + } const std::string m_address; int m_port; @@ -100,103 +95,23 @@ private: DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory); }; -class DevToolsDiscoveryProviderQt : public DevToolsDiscoveryManager::Provider { -public: - DevToolsTargetDescriptor::List GetDescriptors() override; -}; - -class Target : public DevToolsTargetDescriptor { -public: - explicit Target(scoped_refptr<DevToolsAgentHost> agent_host); - - virtual std::string GetId() const override { return agent_host_->GetId(); } - virtual std::string GetParentId() const override { return std::string(); } - virtual std::string GetType() const override { - switch (agent_host_->GetType()) { - case DevToolsAgentHost::TYPE_WEB_CONTENTS: - return kTargetTypePage; - case DevToolsAgentHost::TYPE_SHARED_WORKER: - return kTargetTypeSharedWorker; - case DevToolsAgentHost::TYPE_SERVICE_WORKER: - return kTargetTypeServiceWorker; - default: - break; - } - return kTargetTypeOther; - } - virtual std::string GetTitle() const override { return agent_host_->GetTitle(); } - virtual std::string GetDescription() const override { return std::string(); } - virtual GURL GetURL() const override { return agent_host_->GetURL(); } - virtual GURL GetFaviconURL() const override { return favicon_url_; } - virtual base::TimeTicks GetLastActivityTime() const override { - return last_activity_time_; - } - virtual bool IsAttached() const override { - return agent_host_->IsAttached(); - } - virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const override { - return agent_host_; - } - virtual bool Activate() const override; - virtual bool Close() const override; - -private: - scoped_refptr<DevToolsAgentHost> agent_host_; - GURL favicon_url_; - base::TimeTicks last_activity_time_; -}; - -Target::Target(scoped_refptr<DevToolsAgentHost> agent_host) - : agent_host_(agent_host) -{ - if (WebContents* web_contents = agent_host_->GetWebContents()) { - NavigationController& controller = web_contents->GetController(); - NavigationEntry* entry = controller.GetActiveEntry(); - if (entry != NULL && entry->GetURL().is_valid()) - favicon_url_ = entry->GetFavicon().url; - last_activity_time_ = web_contents->GetLastActiveTime(); - } -} - -bool Target::Activate() const { - return agent_host_->Activate(); -} - -bool Target::Close() const { - return agent_host_->Close(); -} - -DevToolsTargetDescriptor::List DevToolsDiscoveryProviderQt::GetDescriptors() -{ - DevToolsTargetDescriptor::List targets; - for (const auto& agent_host : DevToolsAgentHost::GetOrCreateAll()) { - targets.push_back(new Target(agent_host)); - } - return targets; -} - } // namespace namespace QtWebEngineCore { -std::unique_ptr<DevToolsHttpHandler> createDevToolsHttpHandler() -{ - DevToolsHttpHandlerDelegateQt *delegate = new DevToolsHttpHandlerDelegateQt(); - if (!delegate->isValid()) { - delete delegate; - return nullptr; - } - std::unique_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(new TCPServerSocketFactory(delegate->bindAddress().toStdString(), delegate->port(), 1)); - // Ownership of the delegate is taken over the devtools http handler. - std::unique_ptr<DevToolsHttpHandler> handler(new DevToolsHttpHandler(std::move(factory), std::string(), delegate, base::FilePath(), base::FilePath(), std::string(), std::string())); - DevToolsDiscoveryManager::GetInstance()->AddProvider(base::WrapUnique(new DevToolsDiscoveryProviderQt())); - return std::move(handler); -} - -DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt() +DevToolsServerQt::DevToolsServerQt() : m_bindAddress(QLatin1String("127.0.0.1")) , m_port(0) , m_valid(false) + , m_isStarted(false) +{ } + +DevToolsServerQt::~DevToolsServerQt() +{ + stop(); +} + +void DevToolsServerQt::parseAddressAndPort() { const QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBENGINE_REMOTE_DEBUGGING")); const base::CommandLine &commandLine = *base::CommandLine::ForCurrentProcess(); @@ -215,21 +130,56 @@ DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt() return; m_port = portStr.toInt(&m_valid); - m_valid = m_valid && m_port > 0 && m_port < 65535; + m_valid = m_valid && (m_port > 0 && m_port < 65535); if (!m_valid) qWarning("Invalid port given for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's network interface).", qPrintable(portStr)); } -void DevToolsHttpHandlerDelegateQt::Initialized(const net::IPEndPoint *ip_address) +std::unique_ptr<content::DevToolsSocketFactory> DevToolsServerQt::CreateSocketFactory() +{ + if (!m_valid) + return nullptr; + return std::unique_ptr<content::DevToolsSocketFactory>( + new TCPServerSocketFactory(m_bindAddress.toStdString(), m_port, 1)); +} + + +void DevToolsServerQt::start() +{ + if (m_isStarted) + return; + + if (!m_valid) + parseAddressAndPort(); + + std::unique_ptr<content::DevToolsSocketFactory> socketFactory = CreateSocketFactory(); + if (!socketFactory) + return; + + m_isStarted = true; + DevToolsAgentHost::StartRemoteDebuggingServer( + std::move(socketFactory), std::string(), + base::FilePath(), base::FilePath(), + std::string(), std::string()); +} + +void DevToolsServerQt::stop() +{ + DevToolsAgentHost::StopRemoteDebuggingServer(); + m_isStarted = false; +} + +void DevToolsManagerDelegateQt::Initialized(const net::IPEndPoint *ip_address) { if (ip_address && ip_address->address().size()) { QString addressAndPort = QString::fromStdString(ip_address->ToString()); qWarning("Remote debugging server started successfully. Try pointing a Chromium-based browser to http://%s", qPrintable(addressAndPort)); - } else - qWarning("Couldn't start the inspector server on bind address \"%s\" and port \"%d\". In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).", qPrintable(m_bindAddress), m_port); + } + else + qWarning("Couldn't start the inspector server on bind address. In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface)."); } -std::string DevToolsHttpHandlerDelegateQt::GetDiscoveryPageHTML() +std::string DevToolsManagerDelegateQt::GetDiscoveryPageHTML() { static std::string html; if (html.empty()) { @@ -241,24 +191,9 @@ std::string DevToolsHttpHandlerDelegateQt::GetDiscoveryPageHTML() return html; } -std::string DevToolsHttpHandlerDelegateQt::GetPageThumbnailData(const GURL& url) -{ - return std::string(); -} - -std::string DevToolsHttpHandlerDelegateQt::GetFrontendResource(const std::string &path) +std::string DevToolsManagerDelegateQt::GetFrontendResource(const std::string& path) { return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); } -content::DevToolsExternalAgentProxyDelegate* DevToolsHttpHandlerDelegateQt::HandleWebSocketConnection(const std::string&) -{ - return 0; -} - -base::DictionaryValue* DevToolsManagerDelegateQt::HandleCommand(DevToolsAgentHost *, base::DictionaryValue *) -{ - return 0; -} - } //namespace QtWebEngineCore diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h index 6512146a5..1b0e82bc0 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.h +++ b/src/core/dev_tools_http_handler_delegate_qt.h @@ -40,51 +40,45 @@ #ifndef DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H #define DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H -#include "components/devtools_http_handler/devtools_http_handler_delegate.h" #include "content/public/browser/devtools_manager_delegate.h" #include <QString> -#include <QtCore/qcompilerdetection.h> // needed for Q_DECL_OVERRIDE namespace content { -class BrowserContext; -} - -namespace devtools_http_handler { -class DevToolsHttpHandler; +class DevToolsSocketFactory; } namespace QtWebEngineCore { -std::unique_ptr<devtools_http_handler::DevToolsHttpHandler> createDevToolsHttpHandler(); - -class DevToolsHttpHandlerDelegateQt : public devtools_http_handler::DevToolsHttpHandlerDelegate { +class DevToolsServerQt { public: - DevToolsHttpHandlerDelegateQt(); + DevToolsServerQt(); + ~DevToolsServerQt(); bool isValid() const { return m_valid; } QString bindAddress() const { return m_bindAddress; } int port() const { return m_port; } - // devtools_http_handler::DevToolsHttpHandlerDelegate Overrides - void Initialized(const net::IPEndPoint *ip_address) Q_DECL_OVERRIDE; - std::string GetDiscoveryPageHTML() Q_DECL_OVERRIDE; - std::string GetFrontendResource(const std::string&) Q_DECL_OVERRIDE; - std::string GetPageThumbnailData(const GURL &url) Q_DECL_OVERRIDE; - - content::DevToolsExternalAgentProxyDelegate* HandleWebSocketConnection(const std::string&) Q_DECL_OVERRIDE; + void start(); + void stop(); + bool isStarted() const { return m_isStarted; } private: + void parseAddressAndPort(); + std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory(); + QString m_bindAddress; int m_port; bool m_valid; + bool m_isStarted; }; + class DevToolsManagerDelegateQt : public content::DevToolsManagerDelegate { public: - void Inspect(content::BrowserContext *browser_context, content::DevToolsAgentHost *agent_host) Q_DECL_OVERRIDE { } - void DevToolsAgentStateChanged(content::DevToolsAgentHost *agent_host, bool attached) Q_DECL_OVERRIDE { } - base::DictionaryValue *HandleCommand(content::DevToolsAgentHost *agent_host, base::DictionaryValue *command) Q_DECL_OVERRIDE; + std::string GetDiscoveryPageHTML() override; + std::string GetFrontendResource(const std::string& path) override; + void Initialized(const net::IPEndPoint *ip_address) override; }; } // namespace QtWebEngineCore diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index a1445d609..77469a8ea 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -61,16 +61,6 @@ namespace QtWebEngineCore { -ASSERT_ENUMS_MATCH(content::DownloadItem::IN_PROGRESS, BrowserContextAdapterClient::DownloadInProgress) -ASSERT_ENUMS_MATCH(content::DownloadItem::COMPLETE, BrowserContextAdapterClient::DownloadCompleted) -ASSERT_ENUMS_MATCH(content::DownloadItem::CANCELLED, BrowserContextAdapterClient::DownloadCancelled) -ASSERT_ENUMS_MATCH(content::DownloadItem::INTERRUPTED, BrowserContextAdapterClient::DownloadInterrupted) - -ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_UNKNOWN, BrowserContextAdapterClient::UnknownSavePageFormat) -ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_ONLY_HTML, BrowserContextAdapterClient::SingleHtmlSaveFormat) -ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, BrowserContextAdapterClient::CompleteHtmlSaveFormat) -ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_MHTML, BrowserContextAdapterClient::MimeHtmlSaveFormat) - DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter) : m_contextAdapter(contextAdapter) , m_currentId(0) @@ -165,7 +155,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i suggestedFilePath, BrowserContextAdapterClient::UnknownSavePageFormat, false /* accepted */, - m_downloadType + m_downloadType, + item->GetLastReason() }; Q_FOREACH (BrowserContextAdapterClient *client, clients) { @@ -254,7 +245,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content suggestedFilePath, suggestedSaveFormat, acceptedByDefault, - BrowserContextAdapterClient::SavePage + BrowserContextAdapterClient::SavePage, + BrowserContextAdapterClient::NoReason }; Q_FOREACH (BrowserContextAdapterClient *client, clients) { @@ -291,7 +283,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa QString(), BrowserContextAdapterClient::UnknownSavePageFormat, true /* accepted */, - m_downloadType + m_downloadType, + download->GetLastReason() }; Q_FOREACH (BrowserContextAdapterClient *client, clients) { diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index e8f77e9ed..30a915598 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -174,6 +174,26 @@ bool GLSurfaceGLX::IsCreateContextSupported() return ExtensionsContain(g_extensions, "GLX_ARB_create_context"); } +bool GLSurfaceGLX::IsCreateContextRobustnessSupported() +{ + return false; // ExtensionsContain(g_extensions, "GLX_ARB_create_context_robustness"); +} + +bool GLSurfaceGLX::IsCreateContextProfileSupported() +{ + return false; // ExtensionsContain(g_extensions, "GLX_ARB_create_context_profile"); +} + +bool GLSurfaceGLX::IsCreateContextES2ProfileSupported() +{ + return ExtensionsContain(g_extensions, "GLX_ARB_create_context_es2_profile"); +} + +bool GLSurfaceGLX::IsOMLSyncControlSupported() +{ + return false; // ExtensionsContain(g_extensions, "GLX_OML_sync_control"); +} + bool GLSurfaceGLX::HasGLXExtension(const char *name) { return ExtensionsContain(g_extensions, name); @@ -189,11 +209,6 @@ const char* GLSurfaceGLX::GetGLXExtensions() return g_extensions; } -bool GLSurfaceGLX::IsCreateContextRobustnessSupported() -{ - return false; -} - bool GLSurfaceQtGLX::InitializeOneOff() { static bool initialized = false; diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro new file mode 100644 index 000000000..28d42aa13 --- /dev/null +++ b/src/core/gn_run.pro @@ -0,0 +1,61 @@ +isQtMinimum(5, 8) { + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private +} + +TEMPLATE = aux + +defineReplace(runGn) { + message("Running: $$1") + !system($$1) { + error("GN run error!") + } +} + +qtConfig(debug_and_release): CONFIG += debug_and_release build_all + +build_pass|!debug_and_release { + + ninja_binary = ninja + gn_binary = gn + + runninja.target = run_ninja + rungn.target = run_gn + + gn_args = $$gnArgs() + + CONFIG(release, debug|release) { + gn_args += is_debug=false + } + + gn_args += "qtwebengine_target=\"$$shell_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" + + !qtConfig(system-gn) { + gn_binary = $$shell_quote($$shell_path($$gnPath())) + } + + !qtConfig(system-ninja) { + ninja_binary = $$shell_quote($$shell_path($$ninjaPath())) + } + + gn_args = $$shell_quote($$gn_args) + gn_src_root = $$shell_quote($$shell_path($$QTWEBENGINE_ROOT/$$getChromiumSrcDir())) + gn_build_root = $$shell_quote($$shell_path($$OUT_PWD/$$getConfigDir())) + rungn.commands = $$runGn($$gn_binary gen $$gn_build_root --args=$$gn_args --root=$$gn_src_root) + QMAKE_EXTRA_TARGETS += rungn + + runninja.commands = $$ninja_binary \$\(NINJAFLAGS\) -C $$shell_quote($$OUT_PWD/$$getConfigDir()) QtWebEngineCore + runninja.depends += rungn + QMAKE_EXTRA_TARGETS += runninja + + build_pass:build_all: default_target.target = all + else: default_target.target = first + default_target.depends = runninja + QMAKE_EXTRA_TARGETS += default_target +} + +!build_pass:debug_and_release { + # Special GNU make target for the meta Makefile that ensures that our debug and release Makefiles won't both run ninja in parallel. + notParallel.target = .NOTPARALLEL + QMAKE_EXTRA_TARGETS += notParallel +} diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro index dc22d14bf..2c6aa5069 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -2,9 +2,14 @@ # 1) invoking gyp through the gyp_qtwebengine script, which in turn makes use of the generated gypi include files # 2) produce a Makefile that will run ninja, and take care of actually building everything. +isQtMinimum(5, 8) { + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private +} + TEMPLATE = aux -cross_compile { +contains(WEBENGINE_CONFIG, embedded_build) { GYP_ARGS = "-D qt_cross_compile=1" posix: GYP_ARGS += "-D os_posix=1" qnx: include(config/embedded_qnx.pri) @@ -148,13 +153,20 @@ for (config, GYP_CONFIG): GYP_ARGS += "-D $$config" } build_pass|!debug_and_release { - ninja.target = invoke_ninja - ninja.commands = $$findOrBuildNinja() \$\(NINJAFLAGS\) -C "$$OUT_PWD/$$getConfigDir()" - QMAKE_EXTRA_TARGETS += ninja + + ninja_binary = ninja + runninja.target = run_ninja + + !qtConfig(system-ninja) { + ninja_binary = $$shell_quote($$shell_path($$ninjaPath())) + } + + runninja.commands = $$ninja_binary \$\(NINJAFLAGS\) -C $$shell_quote($$OUT_PWD/$$getConfigDir()) + QMAKE_EXTRA_TARGETS += runninja build_pass:build_all: default_target.target = all else: default_target.target = first - default_target.depends = ninja + default_target.depends = runninja QMAKE_EXTRA_TARGETS += default_target } else { diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index c07bd4b0c..a507f32d1 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -51,9 +51,9 @@ #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" +#include "device/geolocation/geolocation_provider.h" +#include "device/geolocation/geolocation_provider_impl.h" namespace QtWebEngineCore { @@ -161,8 +161,8 @@ void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos) if (!pos.isValid()) return; Q_ASSERT(m_positionInfoSource->error() == QGeoPositionInfoSource::NoError); - content::Geoposition newPos; - newPos.error_code = content::Geoposition::ERROR_CODE_NONE; + device::Geoposition newPos; + newPos.error_code = device::Geoposition::ERROR_CODE_NONE; newPos.error_message.clear(); newPos.timestamp = toTime(pos.timestamp()); @@ -195,15 +195,15 @@ void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos) void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) { Q_ASSERT(positioningError != QGeoPositionInfoSource::NoError); - content::Geoposition newPos; + device::Geoposition newPos; switch (positioningError) { case QGeoPositionInfoSource::AccessError: - newPos.error_code = content::Geoposition::ERROR_CODE_PERMISSION_DENIED; + newPos.error_code = device::Geoposition::ERROR_CODE_PERMISSION_DENIED; break; case QGeoPositionInfoSource::ClosedError: case QGeoPositionInfoSource::UnknownSourceError: // position unavailable is as good as it gets in Geoposition default: - newPos.error_code = content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + newPos.error_code = device::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; break; } if (m_locationProvider) @@ -212,18 +212,18 @@ void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) void QtPositioningHelper::timeout() { - content::Geoposition newPos; + device::Geoposition newPos; // content::Geoposition::ERROR_CODE_TIMEOUT is not handled properly in the renderer process, and the 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; + newPos.error_code = device::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; if (m_locationProvider) postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); } inline void QtPositioningHelper::postToLocationProvider(const base::Closure &task) { - static_cast<content::GeolocationProviderImpl*>(content::GeolocationProvider::GetInstance())->message_loop()->PostTask(FROM_HERE, task); + static_cast<device::GeolocationProviderImpl*>(device::GeolocationProvider::GetInstance())->task_runner()->PostTask(FROM_HERE, task); } LocationProviderQt::LocationProviderQt() @@ -258,21 +258,21 @@ void LocationProviderQt::StopProvider() QMetaObject::invokeMethod(m_positioningHelper, "stop", Qt::QueuedConnection); } -void LocationProviderQt::RequestRefresh() +void LocationProviderQt::OnPermissionGranted() { if (m_positioningHelper) QMetaObject::invokeMethod(m_positioningHelper, "refresh", Qt::QueuedConnection); } -void LocationProviderQt::OnPermissionGranted() +void LocationProviderQt::SetUpdateCallback(const LocationProviderUpdateCallback& callback) { - RequestRefresh(); + m_callback = callback; } -void LocationProviderQt::updatePosition(const content::Geoposition &position) +void LocationProviderQt::updatePosition(const device::Geoposition &position) { m_lastKnownPosition = position; - NotifyCallback(position); + m_callback.Run(this, position); } } // namespace QtWebEngineCore diff --git a/src/core/location_provider_qt.h b/src/core/location_provider_qt.h index b35dcddf9..b1ff354a0 100644 --- a/src/core/location_provider_qt.h +++ b/src/core/location_provider_qt.h @@ -42,8 +42,8 @@ #include <QtCore/qcompilerdetection.h> -#include "content/browser/geolocation/location_provider_base.h" -#include "content/public/common/geoposition.h" +#include "device/geolocation/geoposition.h" +#include "device/geolocation/location_provider.h" QT_FORWARD_DECLARE_CLASS(QThread) @@ -54,25 +54,26 @@ class MessageLoop; namespace QtWebEngineCore { class QtPositioningHelper; -class LocationProviderQt : public content::LocationProviderBase +class LocationProviderQt : public device::LocationProvider { public: LocationProviderQt(); virtual ~LocationProviderQt(); - // LocationProviderBase - virtual bool StartProvider(bool highAccuracy) Q_DECL_OVERRIDE; - virtual void StopProvider() Q_DECL_OVERRIDE; - virtual void GetPosition(content::Geoposition *position) Q_DECL_OVERRIDE { *position = m_lastKnownPosition; } - virtual void RequestRefresh() Q_DECL_OVERRIDE; - virtual void OnPermissionGranted() Q_DECL_OVERRIDE; + // LocationProvider + bool StartProvider(bool high_accuracy) override; + void StopProvider() override; + const device::Geoposition& GetPosition() override { return m_lastKnownPosition; } + void OnPermissionGranted() override; + void SetUpdateCallback(const LocationProviderUpdateCallback& callback) override; private: friend class QtPositioningHelper; - void updatePosition(const content::Geoposition &); + void updatePosition(const device::Geoposition &); - content::Geoposition m_lastKnownPosition; + device::Geoposition m_lastKnownPosition; + LocationProviderUpdateCallback m_callback; QtPositioningHelper *m_positioningHelper; }; //#define QT_USE_POSITIONING 1 diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index f06f0150f..031171bcc 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -50,7 +50,7 @@ #include "web_engine_settings.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/media/desktop_streams_registry.h" +#include "chrome/browser/media/webrtc/desktop_streams_registry.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_capture_devices.h" diff --git a/src/core/ozone_platform_eglfs.cpp b/src/core/ozone_platform_eglfs.cpp index 0b560da6c..e6e1ab5e2 100644 --- a/src/core/ozone_platform_eglfs.cpp +++ b/src/core/ozone_platform_eglfs.cpp @@ -52,7 +52,6 @@ #include "ui/ozone/common/stub_overlay_manager.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/cursor_factory_ozone.h" -#include "ui/ozone/public/gpu_platform_support.h" #include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" @@ -140,10 +139,6 @@ ui::CursorFactoryOzone* OzonePlatformEglfs::GetCursorFactoryOzone() { return cursor_factory_ozone_.get(); } -GpuPlatformSupport* OzonePlatformEglfs::GetGpuPlatformSupport() { - return gpu_platform_support_.get(); -} - GpuPlatformSupportHost* OzonePlatformEglfs::GetGpuPlatformSupportHost() { return gpu_platform_support_host_.get(); } @@ -186,13 +181,12 @@ void OzonePlatformEglfs::InitializeUI() { device_manager_ = CreateDeviceManager(); cursor_factory_ozone_.reset(new CursorFactoryOzone()); event_factory_ozone_.reset(new EventFactoryEvdev(NULL, device_manager_.get(), NULL)); - gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); + gpu_platform_support_host_.reset(ui::CreateStubGpuPlatformSupportHost()); input_controller_ = CreateStubInputController(); } void OzonePlatformEglfs::InitializeGPU() { surface_factory_ozone_.reset(new QtWebEngineCore::SurfaceFactoryQt()); - gpu_platform_support_.reset(CreateStubGpuPlatformSupport()); } } // namespace ui diff --git a/src/core/ozone_platform_eglfs.h b/src/core/ozone_platform_eglfs.h index cdc2bd1ce..c319b1e5c 100644 --- a/src/core/ozone_platform_eglfs.h +++ b/src/core/ozone_platform_eglfs.h @@ -59,7 +59,6 @@ class OzonePlatformEglfs : public OzonePlatform { virtual ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override; virtual ui::CursorFactoryOzone* GetCursorFactoryOzone() override; - virtual GpuPlatformSupport* GetGpuPlatformSupport() override; virtual GpuPlatformSupportHost* GetGpuPlatformSupportHost() override; virtual std::unique_ptr<PlatformWindow> CreatePlatformWindow( PlatformWindowDelegate* delegate, @@ -78,7 +77,6 @@ class OzonePlatformEglfs : public OzonePlatform { std::unique_ptr<CursorFactoryOzone> cursor_factory_ozone_; std::unique_ptr<EventFactoryEvdev> event_factory_ozone_; - std::unique_ptr<GpuPlatformSupport> gpu_platform_support_; std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; std::unique_ptr<InputController> input_controller_; std::unique_ptr<OverlayManagerOzone> overlay_manager_; diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index f76f100e6..970a608a3 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -59,6 +59,7 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type) return BrowserContextAdapter::AudioCapturePermission; case content::PermissionType::VIDEO_CAPTURE: return BrowserContextAdapter::VideoCapturePermission; + case content::PermissionType::FLASH: case content::PermissionType::NOTIFICATIONS: case content::PermissionType::MIDI_SYSEX: case content::PermissionType::PUSH_MESSAGING: @@ -110,6 +111,7 @@ bool PermissionManagerQt::checkPermission(const QUrl &origin, BrowserContextAdap int PermissionManagerQt::RequestPermission(content::PermissionType permission, content::RenderFrameHost *frameHost, const GURL& requesting_origin, + bool /*user_gesture*/, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { int request_id = ++m_requestIdCount; @@ -139,6 +141,7 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission, int PermissionManagerQt::RequestPermissions(const std::vector<content::PermissionType>& permissions, content::RenderFrameHost* frameHost, const GURL& requesting_origin, + bool /*user_gesture*/, const base::Callback<void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) { NOTIMPLEMENTED() << "RequestPermissions has not been implemented in QtWebEngine"; diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index e4392b01c..1cbb41b5e 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -64,6 +64,7 @@ public: content::PermissionType permission, content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, + bool user_gesture, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void CancelPermissionRequest(int request_id) override; @@ -82,6 +83,7 @@ public: const std::vector<content::PermissionType>& permission, content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, + bool user_gesture, const base::Callback<void( const std::vector<blink::mojom::PermissionStatus>&)>& callback) override; diff --git a/src/core/print_view_manager_base_qt.cpp b/src/core/print_view_manager_base_qt.cpp index 8c52e1b18..63181e640 100644 --- a/src/core/print_view_manager_base_qt.cpp +++ b/src/core/print_view_manager_base_qt.cpp @@ -44,6 +44,8 @@ #include "type_conversion.h" #include "web_engine_context.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/timer/timer.h" #include "base/values.h" @@ -62,16 +64,6 @@ namespace QtWebEngineCore { -PrintViewManagerBaseQt::~PrintViewManagerBaseQt() -{ -} - -// PrintedPagesSource implementation. -base::string16 PrintViewManagerBaseQt::RenderSourceName() -{ - return toString16(QLatin1String("")); -} - PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) , m_isInsideInnerMessageLoop(false) @@ -79,84 +71,20 @@ PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) { - -} - -void PrintViewManagerBaseQt::OnNotifyPrintJobEvent( - const printing::JobEventDetails& event_details) { - switch (event_details.type()) { - case printing::JobEventDetails::FAILED: { - TerminatePrintJob(true); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_PRINT_JOB_RELEASED, - content::Source<content::WebContents>(web_contents()), - content::NotificationService::NoDetails()); - break; - } - case printing::JobEventDetails::USER_INIT_DONE: - case printing::JobEventDetails::DEFAULT_INIT_DONE: - case printing::JobEventDetails::USER_INIT_CANCELED: { - NOTREACHED(); - break; - } - case printing::JobEventDetails::ALL_PAGES_REQUESTED: { - break; - } - case printing::JobEventDetails::NEW_DOC: - case printing::JobEventDetails::NEW_PAGE: - case printing::JobEventDetails::PAGE_DONE: - case printing::JobEventDetails::DOC_DONE: { - // Don't care about the actual printing process. - break; - } - case printing::JobEventDetails::JOB_DONE: { - // Printing is done, we don't need it anymore. - // print_job_->is_job_pending() may still be true, depending on the order - // of object registration. - m_didPrintingSucceed = true; - ReleasePrintJob(); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_PRINT_JOB_RELEASED, - content::Source<content::WebContents>(web_contents()), - content::NotificationService::NoDetails()); - break; - } - default: { - NOTREACHED(); - break; - } - } } - -// content::WebContentsObserver implementation. -// Cancels the print job. -void PrintViewManagerBaseQt::NavigationStopped() +PrintViewManagerBaseQt::~PrintViewManagerBaseQt() { + ReleasePrinterQuery(); + DisconnectFromCurrentPrintJob(); } -// content::WebContentsObserver implementation. -void PrintViewManagerBaseQt::DidStartLoading() +void PrintViewManagerBaseQt::NavigationStopped() { + // Cancel the current job, wait for the worker to finish. + TerminatePrintJob(true); } -// content::NotificationObserver implementation. -void PrintViewManagerBaseQt::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - switch (type) { - case chrome::NOTIFICATION_PRINT_JOB_EVENT: - OnNotifyPrintJobEvent(*content::Details<printing::JobEventDetails>(details).ptr()); - break; - default: - NOTREACHED(); - break; - - } -} // Terminates or cancels the print job if one was pending. void PrintViewManagerBaseQt::RenderProcessGone(base::TerminationStatus status) { @@ -175,55 +103,11 @@ void PrintViewManagerBaseQt::RenderProcessGone(base::TerminationStatus status) } } -void PrintViewManagerBaseQt::ReleasePrinterQuery() { - if (!cookie_) - return; - - int cookie = cookie_; - cookie_ = 0; - - printing::PrintJobManager* printJobManager = - WebEngineContext::current()->getPrintJobManager(); - // May be NULL in tests. - if (!printJobManager) - return; - - scoped_refptr<printing::PrinterQuery> printerQuery; - printerQuery = m_printerQueriesQueue->PopPrinterQuery(cookie); - if (!printerQuery.get()) - return; - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&printing::PrinterQuery::StopWorker, printerQuery.get())); -} - - -// content::WebContentsObserver implementation. -bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message) +base::string16 PrintViewManagerBaseQt::RenderSourceName() { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) - IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, - OnShowInvalidPrinterSettingsError); - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled || PrintManager::OnMessageReceived(message); -} - -void PrintViewManagerBaseQt::StopWorker(int documentCookie) { - if (documentCookie <= 0) - return; - scoped_refptr<printing::PrinterQuery> printer_query = - m_printerQueriesQueue->PopPrinterQuery(documentCookie); - if (printer_query.get()) { - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&printing::PrinterQuery::StopWorker, - printer_query)); - } + return toString16(QLatin1String("")); } - // IPC handlers void PrintViewManagerBaseQt::OnDidPrintPage( const PrintHostMsg_DidPrintPage_Params& params) { @@ -304,121 +188,70 @@ void PrintViewManagerBaseQt::OnShowInvalidPrinterSettingsError() { } -bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrintJobWorkerOwner* job) { - DCHECK(!m_isInsideInnerMessageLoop); - - // Disconnect the current print_job_. - DisconnectFromCurrentPrintJob(); - - // We can't print if there is no renderer. - if (!web_contents()->GetRenderViewHost() || - !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { - return false; - } - - // Ask the renderer to generate the print preview, create the print preview - // view and switch to it, initialize the printer and show the print dialog. - DCHECK(!m_printJob.get()); - DCHECK(job); - if (!job) - return false; - - m_printJob = new printing::PrintJob(); - m_printJob->Initialize(job, this, number_pages_); - m_registrar.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, - content::Source<printing::PrintJob>(m_printJob.get())); - m_didPrintingSucceed = false; - return true; -} - -void PrintViewManagerBaseQt::DisconnectFromCurrentPrintJob() { - // Make sure all the necessary rendered page are done. Don't bother with the - // return value. - bool result = RenderAllMissingPagesNow(); - - // Verify that assertion. - if (m_printJob.get() && - m_printJob->document() && - !m_printJob->document()->IsComplete()) { - DCHECK(!result); - // That failed. - TerminatePrintJob(true); - } else { - // DO NOT wait for the job to finish. - ReleasePrintJob(); - } -#if !defined(OS_MACOSX) - m_isExpectingFirstPage = true; -#endif +void PrintViewManagerBaseQt::DidStartLoading() +{ } -void PrintViewManagerBaseQt::PrintingDone(bool success) { - if (!m_printJob.get()) - return; - Send(new PrintMsg_PrintingDone(routing_id(), success)); +bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message) +{ + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) + IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, + OnShowInvalidPrinterSettingsError); + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled || PrintManager::OnMessageReceived(message); } -void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) { - if (!m_printJob.get()) - return; - - if (cancel) { - // We don't need the metafile data anymore because the printing is canceled. - m_printJob->Cancel(); - m_isInsideInnerMessageLoop = false; - } else { - DCHECK(!m_isInsideInnerMessageLoop); - DCHECK(!m_printJob->document() || m_printJob->document()->IsComplete()); - - // WebContents is either dying or navigating elsewhere. We need to render - // all the pages in an hurry if a print job is still pending. This does the - // trick since it runs a blocking message loop: - m_printJob->Stop(); - } - ReleasePrintJob(); +void PrintViewManagerBaseQt::Observe(int type, + const content::NotificationSource& /*source*/, + const content::NotificationDetails& details) +{ + DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type); + OnNotifyPrintJobEvent(*content::Details<printing::JobEventDetails>(details).ptr()); } -bool PrintViewManagerBaseQt::OpportunisticallyCreatePrintJob(int cookie) +void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details) { - if (m_printJob.get()) - return true; - - if (!cookie) { - // Out of sync. It may happens since we are completely asynchronous. Old - // spurious message can happen if one of the processes is overloaded. - return false; - } - - // The job was initiated by a script. Time to get the corresponding worker - // thread. - scoped_refptr<printing::PrinterQuery> queued_query = m_printerQueriesQueue->PopPrinterQuery(cookie); - if (!queued_query.get()) { - NOTREACHED(); - return false; - } - - if (!CreateNewPrintJob(queued_query.get())) { - // Don't kill anything. - return false; + switch (event_details.type()) { + case printing::JobEventDetails::FAILED: + TerminatePrintJob(true); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source<content::WebContents>(web_contents()), + content::NotificationService::NoDetails()); + break; + case printing::JobEventDetails::USER_INIT_DONE: + case printing::JobEventDetails::DEFAULT_INIT_DONE: + case printing::JobEventDetails::USER_INIT_CANCELED: + NOTREACHED(); + break; + case printing::JobEventDetails::ALL_PAGES_REQUESTED: + break; + case printing::JobEventDetails::NEW_DOC: + case printing::JobEventDetails::NEW_PAGE: + case printing::JobEventDetails::PAGE_DONE: + case printing::JobEventDetails::DOC_DONE: + // Don't care about the actual printing process. + break; + case printing::JobEventDetails::JOB_DONE: + // Printing is done, we don't need it anymore. + // print_job_->is_job_pending() may still be true, depending on the order + // of object registration. + m_didPrintingSucceed = true; + ReleasePrintJob(); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source<content::WebContents>(web_contents()), + content::NotificationService::NoDetails()); + break; + default: + NOTREACHED(); + break; } - - // Settings are already loaded. Go ahead. This will set - // print_job_->is_job_pending() to true. - m_printJob->StartPrinting(); - return true; -} - -void PrintViewManagerBaseQt::ReleasePrintJob() { - if (!m_printJob.get()) - return; - - PrintingDone(m_didPrintingSucceed); - - m_registrar.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, - content::Source<printing::PrintJob>(m_printJob.get())); - m_printJob->DisconnectSource(); - // Don't close the worker thread. - m_printJob = NULL; } // Requests the RenderView to render all the missing pages for the print job. @@ -461,6 +294,118 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() return true; } +// Quits the current message loop if these conditions hold true: a document is +// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This +// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED +// notification. The inner message loop is created was created by +// RenderAllMissingPagesNow(). +void PrintViewManagerBaseQt::ShouldQuitFromInnerMessageLoop() +{ + // Look at the reason. + DCHECK(m_printJob->document()); + if (m_printJob->document() && + m_printJob->document()->IsComplete() && + m_isInsideInnerMessageLoop) { + // We are in a message loop created by RenderAllMissingPagesNow. Quit from + // it. + base::MessageLoop::current()->QuitWhenIdle(); + m_isInsideInnerMessageLoop = false; + } +} + +bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrintJobWorkerOwner* job) +{ + DCHECK(!m_isInsideInnerMessageLoop); + + // Disconnect the current print_job_. + DisconnectFromCurrentPrintJob(); + + // We can't print if there is no renderer. + if (!web_contents()->GetRenderViewHost() || + !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { + return false; + } + + // Ask the renderer to generate the print preview, create the print preview + // view and switch to it, initialize the printer and show the print dialog. + DCHECK(!m_printJob.get()); + DCHECK(job); + if (!job) + return false; + + m_printJob = new printing::PrintJob(); + m_printJob->Initialize(job, this, number_pages_); + m_registrar.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, + content::Source<printing::PrintJob>(m_printJob.get())); + m_didPrintingSucceed = false; + return true; +} + +void PrintViewManagerBaseQt::DisconnectFromCurrentPrintJob() +{ + // Make sure all the necessary rendered page are done. Don't bother with the + // return value. + bool result = RenderAllMissingPagesNow(); + + // Verify that assertion. + if (m_printJob.get() && + m_printJob->document() && + !m_printJob->document()->IsComplete()) { + DCHECK(!result); + // That failed. + TerminatePrintJob(true); + } else { + // DO NOT wait for the job to finish. + ReleasePrintJob(); + } +#if !defined(OS_MACOSX) + m_isExpectingFirstPage = true; +#endif +} + +void PrintViewManagerBaseQt::PrintingDone(bool success) +{ + if (!m_printJob.get()) + return; + Send(new PrintMsg_PrintingDone(routing_id(), success)); +} + +void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) +{ + if (!m_printJob.get()) + return; + + if (cancel) { + // We don't need the metafile data anymore because the printing is canceled. + m_printJob->Cancel(); + m_isInsideInnerMessageLoop = false; + } else { + DCHECK(!m_isInsideInnerMessageLoop); + DCHECK(!m_printJob->document() || m_printJob->document()->IsComplete()); + + // WebContents is either dying or navigating elsewhere. We need to render + // all the pages in an hurry if a print job is still pending. This does the + // trick since it runs a blocking message loop: + m_printJob->Stop(); + } + ReleasePrintJob(); +} + +void PrintViewManagerBaseQt::ReleasePrintJob() +{ + if (!m_printJob.get()) + return; + + PrintingDone(m_didPrintingSucceed); + + m_registrar.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, + content::Source<printing::PrintJob>(m_printJob.get())); + m_printJob->DisconnectSource(); + // Don't close the worker thread. + m_printJob = NULL; +} + + bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // This value may actually be too low: // @@ -483,9 +428,11 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // Need to enable recursive task. { - base::MessageLoop::ScopedNestableTaskAllower allow( - base::MessageLoop::current()); - base::MessageLoop::current()->Run(); + base::RunLoop runLoop; + m_quitClosure = runLoop.QuitClosure(); + base::MessageLoop* loop = base::MessageLoop::current(); + base::MessageLoop::ScopedNestableTaskAllower allowNested(loop); + runLoop.Run(); } bool success = true; @@ -498,23 +445,69 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop() { return success; } -// Quits the current message loop if these conditions hold true: a document is -// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This -// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED -// notification. The inner message loop is created was created by -// RenderAllMissingPagesNow(). -void PrintViewManagerBaseQt::ShouldQuitFromInnerMessageLoop() +bool PrintViewManagerBaseQt::OpportunisticallyCreatePrintJob(int cookie) { - // Look at the reason. - DCHECK(m_printJob->document()); - if (m_printJob->document() && - m_printJob->document()->IsComplete() && - m_isInsideInnerMessageLoop) { - // We are in a message loop created by RenderAllMissingPagesNow. Quit from - // it. - base::MessageLoop::current()->QuitWhenIdle(); - m_isInsideInnerMessageLoop = false; + if (m_printJob.get()) + return true; + + if (!cookie) { + // Out of sync. It may happens since we are completely asynchronous. Old + // spurious message can happen if one of the processes is overloaded. + return false; } + + // The job was initiated by a script. Time to get the corresponding worker + // thread. + scoped_refptr<printing::PrinterQuery> queued_query = m_printerQueriesQueue->PopPrinterQuery(cookie); + if (!queued_query.get()) { + NOTREACHED(); + return false; + } + + if (!CreateNewPrintJob(queued_query.get())) { + // Don't kill anything. + return false; + } + + // Settings are already loaded. Go ahead. This will set + // print_job_->is_job_pending() to true. + m_printJob->StartPrinting(); + return true; +} + +void PrintViewManagerBaseQt::ReleasePrinterQuery() +{ + if (!cookie_) + return; + + int cookie = cookie_; + cookie_ = 0; + + printing::PrintJobManager* printJobManager = WebEngineContext::current()->getPrintJobManager(); + // May be NULL in tests. + if (!printJobManager) + return; + + scoped_refptr<printing::PrinterQuery> printerQuery; + printerQuery = m_printerQueriesQueue->PopPrinterQuery(cookie); + if (!printerQuery.get()) + return; + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&printing::PrinterQuery::StopWorker, printerQuery.get())); +} + +// Originally from print_preview_message_handler.cc: +void PrintViewManagerBaseQt::StopWorker(int documentCookie) { + if (documentCookie <= 0) + return; + scoped_refptr<printing::PrinterQuery> printer_query = + m_printerQueriesQueue->PopPrinterQuery(documentCookie); + if (printer_query.get()) { + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&printing::PrinterQuery::StopWorker, + printer_query)); + } } } // namespace QtWebEngineCore diff --git a/src/core/print_view_manager_base_qt.h b/src/core/print_view_manager_base_qt.h index a8b4b5fc8..27dda5ef6 100644 --- a/src/core/print_view_manager_base_qt.h +++ b/src/core/print_view_manager_base_qt.h @@ -135,6 +135,8 @@ protected: private: content::NotificationRegistrar m_registrar; scoped_refptr<printing::PrintJob> m_printJob; + // Closure for quitting nested message loop. + base::Closure m_quitClosure; bool m_isInsideInnerMessageLoop; bool m_isExpectingFirstPage; diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp index 0231df8bd..6006c3bad 100644 --- a/src/core/print_view_manager_qt.cpp +++ b/src/core/print_view_manager_qt.cpp @@ -63,7 +63,8 @@ namespace { static const qreal kMicronsToMillimeter = 1000.0f; static std::vector<char> -GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { +GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) +{ std::unique_ptr<base::SharedMemory> shared_buf( new base::SharedMemory(handle, true)); @@ -76,7 +77,8 @@ GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { } static scoped_refptr<base::RefCountedBytes> -GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { +GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) +{ std::unique_ptr<base::SharedMemory> shared_buf( new base::SharedMemory(handle, true)); @@ -91,7 +93,10 @@ GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { // Write the PDF file to disk. static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, - const base::FilePath& path) { + const base::FilePath& path, + const QtWebEngineCore::PrintViewManagerQt::PrintToPDFFileCallback + &saveCallback) +{ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); DCHECK_GT(data->size(), 0U); @@ -100,8 +105,10 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data, base::File file(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - if (file.IsValid()) - metafile.SaveTo(&file); + bool success = file.IsValid() && metafile.SaveTo(&file); + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(saveCallback, success)); } static base::DictionaryValue *createPrintSettings() @@ -172,30 +179,43 @@ PrintViewManagerQt::~PrintViewManagerQt() } #if defined(ENABLE_BASIC_PRINTING) -bool PrintViewManagerQt::PrintToPDF(const QPageLayout &pageLayout, bool printInColor, const QString &filePath) +void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayout, + bool printInColor, const QString &filePath, + const PrintToPDFFileCallback& callback) { - if (m_printSettings || !filePath.length()) - return false; + if (callback.is_null()) + return; + + if (m_printSettings || !filePath.length()) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, false)); + return; + } m_pdfOutputPath = toFilePath(filePath); + m_pdfSaveCallback = callback; if (!PrintToPDFInternal(pageLayout, printInColor)) { + content::BrowserThread::PostTask(content::BrowserThread::UI, + FROM_HERE, + base::Bind(callback, false)); resetPdfState(); - return false; } - return true; } -bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, bool printInColor, const PrintToPDFCallback& callback) +void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, + bool printInColor, + const PrintToPDFCallback& callback) { if (callback.is_null()) - return false; + return; // If there already is a pending print in progress, don't try starting another one. if (m_printSettings) { content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(callback, std::vector<char>())); - return false; + return; } m_pdfPrintCallback = callback; @@ -205,9 +225,7 @@ bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, b base::Bind(callback, std::vector<char>())); resetPdfState(); - return false; } - return true; } bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, bool printInColor) @@ -218,7 +236,8 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, bool m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout)); m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds , web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds); - m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE); + m_printSettings->SetInteger(printing::kSettingColor, + printInColor ? printing::COLOR : printing::GRAYSCALE); return Send(new PrintMsg_InitiatePrintPreview(routing_id(), false)); } @@ -255,6 +274,7 @@ void PrintViewManagerQt::resetPdfState() { m_pdfOutputPath.clear(); m_pdfPrintCallback.Reset(); + m_pdfSaveCallback.Reset(); m_printSettings.reset(); } @@ -273,20 +293,23 @@ void PrintViewManagerQt::OnMetafileReadyForPrinting( // Create local copies so we can reset the state and take a new pdf print job. base::Callback<void(const std::vector<char>&)> pdf_print_callback = m_pdfPrintCallback; + base::Callback<void(bool)> pdf_save_callback = m_pdfSaveCallback; base::FilePath pdfOutputPath = m_pdfOutputPath; resetPdfState(); if (!pdf_print_callback.is_null()) { - std::vector<char> data_vector = GetStdVectorFromHandle(params.metafile_data_handle, params.data_size); + std::vector<char> data_vector = GetStdVectorFromHandle(params.metafile_data_handle, + params.data_size); content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(pdf_print_callback, data_vector)); } else { - scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.metafile_data_handle, params.data_size); + scoped_refptr<base::RefCountedBytes> data_bytes + = GetBytesFromHandle(params.metafile_data_handle, params.data_size); content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, - base::Bind(&SavePdfFile, data_bytes, pdfOutputPath)); + base::Bind(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback)); } } diff --git a/src/core/print_view_manager_qt.h b/src/core/print_view_manager_qt.h index 668516096..b2ba73b27 100644 --- a/src/core/print_view_manager_qt.h +++ b/src/core/print_view_manager_qt.h @@ -81,10 +81,16 @@ class PrintViewManagerQt public: ~PrintViewManagerQt() override; typedef base::Callback<void(const std::vector<char> &result)> PrintToPDFCallback; + typedef base::Callback<void(bool success)> PrintToPDFFileCallback; #if defined(ENABLE_BASIC_PRINTING) // Method to print a page to a Pdf document with page size \a pageSize in location \a filePath. - bool PrintToPDF(const QPageLayout &pageLayout, bool printInColor, const QString &filePath); - bool PrintToPDFWithCallback(const QPageLayout &pageLayout, bool printInColor, const PrintToPDFCallback &callback); + void PrintToPDFFileWithCallback(const QPageLayout &pageLayout, + bool printInColor, + const QString &filePath, + const PrintToPDFFileCallback& callback); + void PrintToPDFWithCallback(const QPageLayout &pageLayout, + bool printInColor, + const PrintToPDFCallback &callback); #endif // ENABLE_BASIC_PRINTING // PrintedPagesSource implementation. @@ -114,6 +120,7 @@ protected: base::FilePath m_pdfOutputPath; PrintToPDFCallback m_pdfPrintCallback; + PrintToPDFFileCallback m_pdfSaveCallback; private: friend class content::WebContentsUserData<PrintViewManagerQt>; diff --git a/src/core/printing_message_filter_qt.cpp b/src/core/printing_message_filter_qt.cpp index a84ec491f..49940d7ee 100644 --- a/src/core/printing_message_filter_qt.cpp +++ b/src/core/printing_message_filter_qt.cpp @@ -111,6 +111,7 @@ void PrintingMessageFilterQt::OnGetDefaultPrintSettings(IPC::Message* reply_msg) false, printing::DEFAULT_MARGINS, false, + false, base::Bind(&PrintingMessageFilterQt::OnGetDefaultPrintSettingsReply, this, printer_query, @@ -156,6 +157,7 @@ void PrintingMessageFilterQt::OnScriptedPrint( params.has_selection, params.margin_type, params.is_scripted, + params.is_modifiable, base::Bind(&PrintingMessageFilterQt::OnScriptedPrintReply, this, printer_query, diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni new file mode 100644 index 000000000..8fa018038 --- /dev/null +++ b/src/core/qtwebengine.gni @@ -0,0 +1,44 @@ +import("//third_party/widevine/cdm/widevine.gni") + +chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("//chrome/VERSION"), + "-t", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"], + "list lines") + +include_dirs = [ + "//skia/config", + "//third_party/skia/include/core" +] + +deps = [ + "//base", + "//components/error_page/common", + "//components/keyed_service/content", + "//components/visitedlink/browser", + "//components/visitedlink/renderer", + "//components/web_cache/browser", + "//components/web_cache/renderer", + "//content/public/app:browser", + "//content/public/browser", + "//content/public/common", + "//content/public/renderer", + "//net:net_browser_services", + "//skia", + "//third_party/WebKit/public:blink", + "//third_party/widevine/cdm:version_h", + "//ui/accessibility", + "//third_party/mesa:mesa_headers", + ":qtwebengine_sources", + ":qtwebengine_resources" +] + +if (enable_widevine) { + deps += [ "//components/cdm/renderer"] +} + +if (is_linux && !is_desktop_linux) { + deps += [ "//ui/events/ozone:events_ozone_evdev"] +} + +defines = [ + "CHROMIUM_VERSION=\"" + chromium_version[0] + "\"" +] diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi index cd8d9cb5d..b83b1cbfa 100644 --- a/src/core/qtwebengine.gypi +++ b/src/core/qtwebengine.gypi @@ -131,16 +131,6 @@ '<(chromium_src_dir)/components/components.gyp:printing_browser', '<(chromium_src_dir)/components/components.gyp:printing_common', '<(chromium_src_dir)/components/components.gyp:printing_renderer', - ], - 'sources': [ - 'printing_message_filter_qt.cpp', - 'print_view_manager_base_qt.cpp', - 'print_view_manager_qt.cpp', - 'printing_message_filter_qt.h', - 'print_view_manager_base_qt.h', - 'print_view_manager_qt.h', - 'renderer/print_web_view_helper_delegate_qt.cpp', - 'renderer/print_web_view_helper_delegate_qt.h', ] }], ['icu_use_data_file_flag==1', { diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni new file mode 100644 index 000000000..a7ffb40f3 --- /dev/null +++ b/src/core/qtwebengine_resources.gni @@ -0,0 +1,86 @@ +import("//tools/grit/repack.gni") +import("//build/config/locales.gni") +import("//chrome/chrome_repack_locales.gni") + +group("qtwebengine_resources") { + deps = [ + "//chrome/app:generated_resources", + "//components/resources:components_resources", + ":qtwebengine_repack_resources", + ":qtwebengine_repack_resources_100", + ":qtwebengine_repack_resources_200", + ":qtwebengine_repack_resources_devtools", + ":qtwebengine_repack_locales_pack" + ] +} + +repack("qtwebengine_repack_resources") { + sources = [ + "$root_gen_dir/blink/public/resources/blink_resources.pak", + "$root_gen_dir/components/components_resources.pak", + "$root_gen_dir/content/content_resources.pak", + "$root_gen_dir/net/net_resources.pak", + "$root_gen_dir/ui/resources/webui_resources.pak", + ] + output = "$root_out_dir/qtwebengine_resources.pak" + deps = [ + "//components/resources:components_resources_grit", + "//content:resources_grit", + "//net:net_resources_grit", + "//third_party/WebKit/public:resources_grit", + "//ui/resources:webui_resources_grd_grit", + ] +} + +repack("qtwebengine_repack_resources_100") { + sources = [ + "$root_gen_dir/ui/resources/ui_resources_100_percent.pak", + "$root_gen_dir/components/components_resources_100_percent.pak", + "$root_gen_dir/content/app/resources/content_resources_100_percent.pak", + "$root_gen_dir/chrome/renderer_resources_100_percent.pak", + "$root_gen_dir/blink/public/resources/blink_image_resources_100_percent.pak", + ] + output = "$root_out_dir/qtwebengine_resources_100p.pak" + deps = [ + "//third_party/WebKit/public:image_resources_grit", + "//chrome/renderer:resources_grit", + "//components/resources:components_scaled_resources_grit", + "//content/app/resources:resources_grit", + "//ui/resources:ui_resources_grd_grit" + ] +} + +repack("qtwebengine_repack_resources_200") { + sources = [ + "$root_gen_dir/ui/resources/ui_resources_200_percent.pak", + "$root_gen_dir/components/components_resources_200_percent.pak", + "$root_gen_dir/content/app/resources/content_resources_200_percent.pak", + "$root_gen_dir/chrome/renderer_resources_200_percent.pak", + "$root_gen_dir/blink/public/resources/blink_image_resources_200_percent.pak", + ] + output = "$root_out_dir/qtwebengine_resources_200p.pak" + deps = [ + "//third_party/WebKit/public:image_resources_grit", + "//chrome/renderer:resources_grit", + "//components/resources:components_scaled_resources_grit", + "//content/app/resources:resources_grit", + "//ui/resources:ui_resources_grd_grit" + ] +} + +repack("qtwebengine_repack_resources_devtools") { + sources = [ + "$root_gen_dir/blink/devtools_resources.pak", + ] + output = "$root_out_dir/qtwebengine_devtools_resources.pak" + deps = [ + "//content/browser/devtools:devtools_resources_grit" + ] +} + +chrome_repack_locales("qtwebengine_repack_locales_pack") { + input_locales = locales + output_dir = "$root_out_dir/qtwebengine_locales" + output_locales = locales +} + diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni new file mode 100644 index 000000000..93a0feb72 --- /dev/null +++ b/src/core/qtwebengine_sources.gni @@ -0,0 +1,101 @@ +import("//build/config/features.gni") + +source_set("qtwebengine_spellcheck_sources") { + sources = [ + "//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc", + "//chrome/browser/spellchecker/spellcheck_custom_dictionary.h", + "//chrome/browser/spellchecker/spellcheck_factory.cc", + "//chrome/browser/spellchecker/spellcheck_factory.h", + "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc", + "//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h", + "//chrome/browser/spellchecker/spellcheck_message_filter.cc", + "//chrome/browser/spellchecker/spellcheck_message_filter.h", + "//chrome/browser/spellchecker/spellcheck_service.cc", + "//chrome/browser/spellchecker/spellcheck_service.h", + ] + deps = [ + "//components/spellcheck/browser", + "//components/spellcheck/renderer", + "//third_party/WebKit/public:blink", + "//third_party/hunspell", + ] + if (is_mac && use_browser_spellchecker) { + sources += [ + "//chrome/browser/spellchecker/spellcheck_message_filter_platform.h", + "//chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc", + ] + } +} + +source_set("qtwebengine_sources") { + include_dirs = [ + "//skia/config", + "//third_party/skia/include/core" + ] + deps = [] + sources = [ + "//chrome/browser/media/webrtc/desktop_media_list.h", + "//chrome/browser/media/webrtc/desktop_streams_registry.cc", + "//chrome/browser/media/webrtc/desktop_streams_registry.h", + "//chrome/common/chrome_switches.cc", + "//chrome/common/chrome_switches.h", + "//components/prefs/testing_pref_store.cc", + "//components/prefs/testing_pref_store.h", + "//extensions/common/constants.cc", + "//extensions/common/constants.h", + "//extensions/common/url_pattern.cc", + "//extensions/common/url_pattern.h", + ] + + if (enable_spellcheck) { + sources += [ + "//chrome/common/pref_names.cc", + "//chrome/common/pref_names.h", + ] + deps += [ + ":qtwebengine_spellcheck_sources", + "//chrome/tools/convert_dict", + ] + } + + if (enable_plugins) { + sources += [ + "//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc", + "//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h", + "//chrome/renderer/pepper/pepper_flash_font_file_host.cc", + "//chrome/renderer/pepper/pepper_flash_font_file_host.h", + "//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc", + "//chrome/renderer/pepper/pepper_shared_memory_message_filter.h", + ] + + deps += [ + # Need to depend on //content/ppapi_plugin, which is private, thus depending on parent. + "//content", + ] + } + + if (enable_basic_printing || enable_print_preview) { + sources += [ + "//chrome/browser/printing/printer_query.cc", + "//chrome/browser/printing/printer_query.h", + "//chrome/browser/printing/print_job.cc", + "//chrome/browser/printing/print_job.h", + "//chrome/browser/printing/print_job_manager.cc", + "//chrome/browser/printing/print_job_manager.h", + "//chrome/browser/printing/print_job_worker.cc", + "//chrome/browser/printing/print_job_worker.h", + "//chrome/browser/printing/print_job_worker_owner.cc", + "//chrome/browser/printing/print_job_worker_owner.h", + ] + } + + if (enable_pdf) { + deps += [ + "//pdf", + "//components/printing/browser", + "//components/printing/renderer", + ] + } + +} + diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index a190380b2..f1c69fca3 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -52,10 +52,10 @@ #include "web_event_factory.h" #include "base/command_line.h" -#include "cc/output/compositor_frame_ack.h" +#include "cc/output/direct_renderer.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" -#include "content/browser/renderer_host/input/web_input_event_util.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/text_input_manager.h" #include "content/common/cursors/webcursor.h" #include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/browser_thread.h" @@ -241,9 +241,10 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget , m_currentInputType(ui::TEXT_INPUT_TYPE_NONE) , m_imeInProgress(false) , m_receivedEmptyImeText(false) - , m_anchorPositionWithinSelection(0) - , m_cursorPositionWithinSelection(0) , m_initPending(false) + , m_beginFrameSource(nullptr) + , m_needsBeginFrames(false) + , m_addedFrameObserver(false) { m_host->SetView(this); #ifndef QT_NO_ACCESSIBILITY @@ -251,6 +252,9 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget if (QAccessible::isActive()) content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility(); #endif // QT_NO_ACCESSIBILITY + auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); + m_beginFrameSource.reset(new cc::DelayBasedBeginFrameSource( + base::MakeUnique<cc::DelayBasedTimeSource>(task_runner))); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() @@ -610,22 +614,6 @@ void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params ¶ms) -{ - if (selection_range_.IsValid()) { - if (params.is_anchor_first) { - m_anchorPositionWithinSelection = selection_range_.GetMin() - selection_text_offset_; - m_cursorPositionWithinSelection = selection_range_.GetMax() - selection_text_offset_; - } else { - m_anchorPositionWithinSelection = selection_range_.GetMax() - selection_text_offset_; - m_cursorPositionWithinSelection = selection_range_.GetMin() - selection_text_offset_; - } - } - - gfx::Rect caretRect = gfx::UnionRects(params.anchor_rect, params.focus_rect); - m_cursorRect = QRect(caretRect.x(), caretRect.y(), caretRect.width(), caretRect.height()); -} - void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType color_type) { NOTIMPLEMENTED(); @@ -670,6 +658,8 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, c m_pendingOutputSurfaceId = output_surface_id; Q_ASSERT(frame.delegated_frame_data); Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty()); + if (m_chromiumCompositorData->frameData.get()) + m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); m_chromiumCompositorData->frameData = std::move(frame.delegated_frame_data); m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor; @@ -693,7 +683,7 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, c m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } -void RenderWidgetHostViewQt::GetScreenInfo(blink::WebScreenInfo* results) +void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo* results) { QWindow* window = m_delegate->window(); if (!window) @@ -701,7 +691,7 @@ void RenderWidgetHostViewQt::GetScreenInfo(blink::WebScreenInfo* results) GetScreenInfoFromNativeWindow(window, results); // Support experimental.viewport.devicePixelRatio - results->deviceScaleFactor *= dpiScale(); + results->device_scale_factor *= dpiScale(); } gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() @@ -826,23 +816,34 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) return true; } -QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) const +QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) { switch (query) { case Qt::ImEnabled: return QVariant(m_currentInputType != ui::TEXT_INPUT_TYPE_NONE); - case Qt::ImCursorRectangle: - return m_cursorRect; case Qt::ImFont: return QVariant(); + case Qt::ImCursorRectangle: + // QIBusPlatformInputContext might query ImCursorRectangle before the + // RenderWidgetHostView is created. Without an available view GetSelectionRange() + // returns nullptr. + if (!GetTextInputManager()->GetSelectionRegion()) + return QVariant(); + return toQt(GetTextInputManager()->GetSelectionRegion()->caret_rect); case Qt::ImCursorPosition: - return static_cast<uint>(m_cursorPositionWithinSelection); + Q_ASSERT(GetTextInputManager()->GetSelectionRegion()); + return toQt(GetTextInputManager()->GetSelectionRegion()->focus.edge_top_rounded().x()); case Qt::ImAnchorPosition: - return static_cast<uint>(m_anchorPositionWithinSelection); + Q_ASSERT(GetTextInputManager()->GetSelectionRegion()); + return toQt(GetTextInputManager()->GetSelectionRegion()->anchor.edge_top_rounded().x()); case Qt::ImSurroundingText: return m_surroundingText; - case Qt::ImCurrentSelection: - return toQt(GetSelectedText()); + case Qt::ImCurrentSelection: { + Q_ASSERT(GetTextInputManager()->GetTextSelection()); + base::string16 text; + GetTextInputManager()->GetTextSelection()->GetSelectedText(&text); + return toQt(text); + } case Qt::ImMaximumTextLength: return QVariant(); // No limit. case Qt::ImHints: @@ -860,11 +861,12 @@ void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWit void RenderWidgetHostViewQt::sendDelegatedFrameAck() { - cc::CompositorFrameAck ack; - m_resourcesToRelease.swap(ack.resources); - content::RenderWidgetHostImpl::SendSwapCompositorFrameAck( + m_beginFrameSource->DidFinishFrame(this, 0); + cc::ReturnedResourceArray resources; + m_resourcesToRelease.swap(resources); + content::RenderWidgetHostImpl::SendReclaimCompositorResources( m_host->GetRoutingID(), m_pendingOutputSurfaceId, - m_host->GetProcess()->GetID(), ack); + m_host->GetProcess()->GetID(), true, resources); } void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) @@ -918,7 +920,7 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event, dpiScale()); if ((webEvent.type == blink::WebInputEvent::MouseDown || webEvent.type == blink::WebInputEvent::MouseUp) - && webEvent.button == blink::WebMouseEvent::ButtonNone) { + && webEvent.button == blink::WebMouseEvent::Button::NoButton) { // Blink can only handle the 3 main mouse-buttons and may assert when processing mouse-down for no button. return; } @@ -978,9 +980,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) gfx::Range::InvalidRange(), gfx::Range::InvalidRange().start(), gfx::Range::InvalidRange().end()); - m_host->ImeConfirmComposition(base::string16(), - gfx::Range::InvalidRange(), - false); + m_host->ImeFinishComposingText(false); m_imeInProgress = false; } return; @@ -1097,7 +1097,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) if (!commitString.isEmpty() || replacementLength > 0) { setCompositionString(commitString); - m_host->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), false); + m_host->ImeFinishComposingText(false); // We might get a commit string and a pre-edit string in a single event, which means // we need to confirm the last composition, and start a new composition. @@ -1267,4 +1267,39 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) } } +void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames) +{ + m_needsBeginFrames = needs_begin_frames; + updateNeedsBeginFramesInternal(); +} + +void RenderWidgetHostViewQt::updateNeedsBeginFramesInternal() +{ + if (!m_beginFrameSource) + return; + + if (m_addedFrameObserver == m_needsBeginFrames) + return; + + if (m_needsBeginFrames) + m_beginFrameSource->AddObserver(this); + else + m_beginFrameSource->RemoveObserver(this); + m_addedFrameObserver = m_needsBeginFrames; +} + +bool RenderWidgetHostViewQt::OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) +{ + m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval); + m_host->Send(new ViewMsg_BeginFrame(m_host->GetRoutingID(), args)); + return true; +} + +void RenderWidgetHostViewQt::OnBeginFrameSourcePausedChanged(bool paused) +{ + // Ignored for now. If the begin frame source is paused, the renderer + // doesn't need to be informed about it and will just not receive more + // begin frames. +} + } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 2f5d97b67..8871d88ce 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -43,6 +43,7 @@ #include "render_widget_host_view_qt_delegate.h" #include "base/memory/weak_ptr.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/resources/transferable_resource.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" @@ -99,6 +100,7 @@ class RenderWidgetHostViewQt , public ui::GestureProviderClient , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> + , public cc::BeginFrameObserverBase #ifndef QT_NO_ACCESSIBILITY , public QAccessible::ActivationObserver #endif // QT_NO_ACCESSIBILITY @@ -144,7 +146,6 @@ public: virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE; virtual void Destroy() Q_DECL_OVERRIDE; virtual void SetTooltipText(const base::string16 &tooltip_text) Q_DECL_OVERRIDE; - virtual void SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params&) Q_DECL_OVERRIDE; virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType preferred_color_type) Q_DECL_OVERRIDE; virtual void CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(const gfx::Rect&, bool)>& callback) Q_DECL_OVERRIDE; @@ -152,12 +153,13 @@ public: virtual bool HasAcceleratedSurface(const gfx::Size&) Q_DECL_OVERRIDE; virtual void OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) Q_DECL_OVERRIDE; - virtual void GetScreenInfo(blink::WebScreenInfo* results) Q_DECL_OVERRIDE; + void GetScreenInfo(content::ScreenInfo* results); virtual gfx::Rect GetBoundsInRootWindow() Q_DECL_OVERRIDE; virtual void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) Q_DECL_OVERRIDE; virtual void ClearCompositorFrame() Q_DECL_OVERRIDE; virtual void LockCompositingSurface() Q_DECL_OVERRIDE; virtual void UnlockCompositingSurface() Q_DECL_OVERRIDE; + virtual void SetNeedsBeginFrames(bool needs_begin_frames) Q_DECL_OVERRIDE; // Overridden from RenderWidgetHostViewBase. virtual void SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range) Q_DECL_OVERRIDE; @@ -173,7 +175,11 @@ public: virtual void windowBoundsChanged() Q_DECL_OVERRIDE; virtual void windowChanged() Q_DECL_OVERRIDE; virtual bool forwardEvent(QEvent *) Q_DECL_OVERRIDE; - virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE; + virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) Q_DECL_OVERRIDE; + + // cc::BeginFrameObserverBase implementation. + bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override; + void OnBeginFrameSourcePausedChanged(bool paused) override; void handleMouseEvent(QMouseEvent*); void handleKeyEvent(QKeyEvent*); @@ -210,6 +216,7 @@ private: void clearPreviousTouchMotionState(); QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints); float dpiScale() const; + void updateNeedsBeginFramesInternal(); bool IsPopup() const; @@ -235,13 +242,14 @@ private: ui::TextInputType m_currentInputType; bool m_imeInProgress; bool m_receivedEmptyImeText; - QRect m_cursorRect; - size_t m_anchorPositionWithinSelection; - size_t m_cursorPositionWithinSelection; QPoint m_lockedMousePosition; bool m_initPending; + std::unique_ptr<cc::SyntheticBeginFrameSource> m_beginFrameSource; + bool m_needsBeginFrames; + bool m_addedFrameObserver; + gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index 1e1234e72..6286596c6 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -84,7 +84,7 @@ public: virtual void windowBoundsChanged() = 0; virtual void windowChanged() = 0; virtual bool forwardEvent(QEvent *) = 0; - virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const = 0; + virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) = 0; }; class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegate { diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 69f5bfefe..ee6ffe420 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -44,8 +44,8 @@ #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #if defined(ENABLE_SPELLCHECK) -#include "chrome/renderer/spellchecker/spellcheck.h" -#include "chrome/renderer/spellchecker/spellcheck_provider.h" +#include "components/spellcheck/renderer/spellcheck.h" +#include "components/spellcheck/renderer/spellcheck_provider.h" #endif #include "components/cdm/renderer/widevine_key_system_properties.h" #include "components/error_page/common/error_page_params.h" @@ -75,6 +75,7 @@ #include "renderer/render_frame_observer_qt.h" #include "renderer/render_view_observer_qt.h" #include "renderer/user_resource_controller.h" +#include "services/shell/public/cpp/interface_registry.h" #include "components/grit/components_resources.h" @@ -98,7 +99,8 @@ void ContentRendererClientQt::RenderThreadStarted() content::RenderThread *renderThread = content::RenderThread::Get(); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - renderThread->AddObserver(m_visitedLinkSlave.data()); + renderThread->GetInterfaceRegistry()->AddInterface( + m_visitedLinkSlave->GetBindCallback()); renderThread->AddObserver(UserResourceController::instance()); #if defined(ENABLE_SPELLCHECK) diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 8c603b805..c89ad69ad 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -39,6 +39,7 @@ #include "user_resource_controller.h" +#include "base/pending_task.h" #include "base/strings/pattern.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" @@ -166,16 +167,16 @@ UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(conte void UserResourceController::RenderViewObserverHelper::DidFinishDocumentLoad(blink::WebLocalFrame *frame) { m_pendingFrames.insert(frame); - base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, - base::Unretained(this), UserScriptData::AfterLoad, frame), - base::TimeDelta::FromMilliseconds(afterLoadTimeout)); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, + base::Unretained(this), UserScriptData::AfterLoad, frame), + base::TimeDelta::FromMilliseconds(afterLoadTimeout)); } void UserResourceController::RenderViewObserverHelper::DidFinishLoad(blink::WebLocalFrame *frame) { // DidFinishDocumentLoad always comes before this, so frame has already been marked as pending. - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, - base::Unretained(this), UserScriptData::AfterLoad, frame)); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts, + base::Unretained(this), UserScriptData::AfterLoad, frame)); } void UserResourceController::RenderViewObserverHelper::DidStartProvisionalLoad(blink::WebLocalFrame *frame) diff --git a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp index 7e8b2fdda..8ebc74486 100644 --- a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp +++ b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp @@ -83,7 +83,7 @@ scoped_refptr<base::TaskRunner> PepperIsolatedFileSystemMessageFilter::OverrideT { // In order to reach ExtensionSystem, we need to get ProfileManager first. // ProfileManager lives in UI thread, so we need to do this in UI thread. - return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::UI); + return content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI); } int32_t PepperIsolatedFileSystemMessageFilter::OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext *context) diff --git a/src/core/ssl_host_state_delegate_qt.cpp b/src/core/ssl_host_state_delegate_qt.cpp index 506172aaa..72aec2bff 100644 --- a/src/core/ssl_host_state_delegate_qt.cpp +++ b/src/core/ssl_host_state_delegate_qt.cpp @@ -34,6 +34,8 @@ ** ****************************************************************************/ +#include "base/callback.h" + #include "ssl_host_state_delegate_qt.h" #include "type_conversion.h" @@ -86,9 +88,21 @@ void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509C } // Clear all allow preferences. -void SSLHostStateDelegateQt::Clear() +void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string&)>& host_filter) { - m_certPolicyforHost.clear(); + if (host_filter.is_null()) { + m_certPolicyforHost.clear(); + return; + } + + for (auto it = m_certPolicyforHost.begin(); it != m_certPolicyforHost.end();) { + auto next_it = std::next(it); + + if (host_filter.Run(it->first)) + m_certPolicyforHost.erase(it); + + it = next_it; + } } // Queries whether |cert| is allowed for |host| and |error|. Returns true in @@ -102,12 +116,12 @@ content::SSLHostStateDelegate::CertJudgment SSLHostStateDelegateQt::QueryPolicy( } // Records that a host has run insecure content. -void SSLHostStateDelegateQt::HostRanInsecureContent(const std::string &host, int pid) +void SSLHostStateDelegateQt::HostRanInsecureContent(const std::string &host, int pid, InsecureContentType content_type) { } // Returns whether the specified host ran insecure content. -bool SSLHostStateDelegateQt::DidHostRunInsecureContent(const std::string &host, int pid) const +bool SSLHostStateDelegateQt::DidHostRunInsecureContent(const std::string &host, int pid, InsecureContentType content_type) const { return false; } diff --git a/src/core/ssl_host_state_delegate_qt.h b/src/core/ssl_host_state_delegate_qt.h index 64a430094..7cc63b339 100644 --- a/src/core/ssl_host_state_delegate_qt.h +++ b/src/core/ssl_host_state_delegate_qt.h @@ -62,11 +62,11 @@ public: // content::SSLHostStateDelegate implementation: virtual void AllowCert(const std::string &, const net::X509Certificate &cert, net::CertStatus error) override; - virtual void Clear() override; + virtual void Clear(const base::Callback<bool(const std::string&)>& host_filter) override; virtual CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, net::CertStatus error,bool *expired_previous_decision) override; - virtual void HostRanInsecureContent(const std::string &host, int pid) override; - virtual bool DidHostRunInsecureContent(const std::string &host, int pid) const override; + virtual void HostRanInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) override; + virtual bool DidHostRunInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) const override; virtual void RevokeUserAllowExceptions(const std::string &host) override; virtual bool HasAllowException(const std::string &host) const override; diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp index 97a304730..36c05ec5d 100644 --- a/src/core/surface_factory_qt.cpp +++ b/src/core/surface_factory_qt.cpp @@ -71,7 +71,7 @@ base::NativeLibrary LoadLibrary(const base::FilePath& filename) { return library; } -bool SurfaceFactoryQt::LoadEGLGLES2Bindings(AddGLLibraryCallback add_gl_library, SetGLGetProcAddressProcCallback set_gl_get_proc_address) +bool SurfaceFactoryQt::LoadEGLGLES2Bindings() { base::FilePath libEGLPath = QtWebEngineCore::toFilePath(QT_LIBDIR_EGL); libEGLPath = libEGLPath.Append("libEGL.so.1"); diff --git a/src/core/surface_factory_qt.h b/src/core/surface_factory_qt.h index d65680a4a..ad6018946 100644 --- a/src/core/surface_factory_qt.h +++ b/src/core/surface_factory_qt.h @@ -51,7 +51,7 @@ namespace QtWebEngineCore { class SurfaceFactoryQt : public ui::SurfaceFactoryOzone { - virtual bool LoadEGLGLES2Bindings(AddGLLibraryCallback add_gl_library, SetGLGetProcAddressProcCallback set_gl_get_proc_address) Q_DECL_OVERRIDE; + virtual bool LoadEGLGLES2Bindings() Q_DECL_OVERRIDE; virtual intptr_t GetNativeDisplay() Q_DECL_OVERRIDE; }; diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 0cfde1cf4..635b7c2d0 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -173,8 +173,8 @@ void URLRequestContextGetterQt::updateStorageSettings() m_proxyConfigService = new ProxyConfigServiceQt( net::ProxyService::CreateSystemProxyConfigService( - content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), - content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) + content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + content::BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE) )); if (m_contextInitialized) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, @@ -477,7 +477,7 @@ void URLRequestContextGetterQt::generateHttpCache() net::CACHE_BACKEND_DEFAULT, base::FilePath(), m_httpCacheMaxSize, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE) ); break; case BrowserContextAdapter::DiskHttpCache: @@ -487,7 +487,7 @@ void URLRequestContextGetterQt::generateHttpCache() net::CACHE_BACKEND_DEFAULT, toFilePath(m_httpCachePath), m_httpCacheMaxSize, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE) ); break; case BrowserContextAdapter::NoCache: @@ -600,7 +600,7 @@ void URLRequestContextGetterQt::regenerateJobFactory() scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const { - return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::IO); + return content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO); } } // namespace QtWebEngineCore diff --git a/src/core/url_request_qrc_job_qt.cpp b/src/core/url_request_qrc_job_qt.cpp index 97460f0b7..b4e960921 100644 --- a/src/core/url_request_qrc_job_qt.cpp +++ b/src/core/url_request_qrc_job_qt.cpp @@ -41,6 +41,8 @@ #include "type_conversion.h" +#include "base/pending_task.h" +#include "base/threading/thread_task_runner_handle.h" #include "net/base/net_errors.h" #include "net/base/io_buffer.h" @@ -67,7 +69,7 @@ URLRequestQrcJobQt::~URLRequestQrcJobQt() void URLRequestQrcJobQt::Start() { - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&URLRequestQrcJobQt::startGetHead, m_weakFactory.GetWeakPtr())); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&URLRequestQrcJobQt::startGetHead, m_weakFactory.GetWeakPtr())); } void URLRequestQrcJobQt::Kill() diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index cff8a025a..7b0712143 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -77,6 +77,7 @@ #include "content/public/common/page_state.h" #include "content/public/common/page_zoom.h" #include "content/public/common/renderer_preferences.h" +#include "content/public/common/resource_request_body.h" #include "content/public/common/url_constants.h" #include "content/public/common/web_preferences.h" #include "third_party/WebKit/public/web/WebFindOptions.h" @@ -183,12 +184,23 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 adapterClient->didRunJavaScript(requestId, fromJSValue(result)); } -static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, int requestId, const std::vector<char>& result) +#if defined(ENABLE_BASIC_PRINTING) +static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, + int requestId, + const std::vector<char>& result) { if (requestId) adapterClient->didPrintPage(requestId, QByteArray(result.data(), result.size())); } +static void callbackOnPdfSavingFinished(WebContentsAdapterClient *adapterClient, + const QString& filePath, + bool success) +{ + adapterClient->didPrintPageToPdf(filePath, success); +} +#endif + static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { content::WebContents::CreateParams create_params(browserContext, NULL); @@ -358,7 +370,7 @@ QSharedPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavig // Unlike WebCore, Chromium only supports Restoring to a new WebContents instance. content::WebContents* newWebContents = createBlankWebContents(adapterClient, adapterClient->browserContextAdapter()->browserContext()); content::NavigationController &controller = newWebContents->GetController(); - controller.Restore(currentIndex, content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, &entries); + controller.Restore(currentIndex, content::RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries); if (controller.GetActiveEntry()) { // Set up the file access rights for the selected navigation entry. @@ -485,6 +497,12 @@ void WebContentsAdapter::reloadAndBypassCache() void WebContentsAdapter::load(const QUrl &url) { + QWebEngineHttpRequest request(url); + load(request); +} + +void WebContentsAdapter::load(const QWebEngineHttpRequest &request) +{ // The situation can occur when relying on the editingFinished signal in QML to set the url // of the WebView. // When enter is pressed, onEditingFinished fires and the url of the webview is set, which @@ -499,21 +517,55 @@ void WebContentsAdapter::load(const QUrl &url) Q_UNUSED(guard); Q_D(WebContentsAdapter); - GURL gurl = toGurl(url); + GURL gurl = toGurl(request.url()); // Add URL scheme if missing from view-source URL. - if (url.scheme() == content::kViewSourceScheme) { - QUrl pageUrl = QUrl(url.toString().remove(0, strlen(content::kViewSourceScheme) + 1)); + if (request.url().scheme() == content::kViewSourceScheme) { + QUrl pageUrl = QUrl(request.url().toString().remove(0, + strlen(content::kViewSourceScheme) + 1)); if (pageUrl.scheme().isEmpty()) { QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString()); - extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, extendedUrl.toString())); + extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, + extendedUrl.toString())); gurl = toGurl(extendedUrl); } } content::NavigationController::LoadURLParams params(gurl); - params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); + params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED + | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; + + switch (request.method()) { + case QWebEngineHttpRequest::Get: + params.load_type = content::NavigationController::LOAD_TYPE_DEFAULT; + break; + + case QWebEngineHttpRequest::Post: + params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST; + // chromium accepts LOAD_TYPE_HTTP_POST only for the HTTP and HTTPS protocols + if (!params.url.SchemeIsHTTPOrHTTPS()) { + d->adapterClient->loadFinished(false, request.url(), false, + net::ERR_DISALLOWED_URL_SCHEME, + QCoreApplication::translate("WebContentsAdapter", + "HTTP-POST data can only be sent over HTTP(S) protocol")); + return; + } + break; + } + + params.post_data = content::ResourceRequestBody::CreateFromBytes( + (const char*)request.postData().constData(), + request.postData().length()); + + // convert the custom headers into the format that chromium expects + QVector<QByteArray> headers = request.headers(); + for (QVector<QByteArray>::const_iterator it = headers.cbegin(); it != headers.cend(); ++it) { + if (params.extra_headers.length() > 0) + params.extra_headers += '\n'; + params.extra_headers += (*it).toStdString() + ": " + request.header(*it).toStdString(); + } + d->webContents->GetController().LoadURLWithParams(params); focusIfNecessary(); } @@ -560,15 +612,17 @@ QUrl WebContentsAdapter::activeUrl() const QUrl WebContentsAdapter::requestedUrl() const { Q_D(const WebContentsAdapter); - content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); - content::NavigationEntry* pendingEntry = d->webContents->GetController().GetPendingEntry(); + if (d->webContents) { + content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); + content::NavigationEntry* pendingEntry = d->webContents->GetController().GetPendingEntry(); - if (entry) { - if (!entry->GetOriginalRequestURL().is_empty()) - return toQt(entry->GetOriginalRequestURL()); + if (entry) { + if (!entry->GetOriginalRequestURL().is_empty()) + return toQt(entry->GetOriginalRequestURL()); - if (pendingEntry && pendingEntry == entry) - return toQt(entry->GetURL()); + if (pendingEntry && pendingEntry == entry) + return toQt(entry->GetURL()); + } } return QUrl(); } @@ -917,7 +971,7 @@ void WebContentsAdapter::inspectElementAt(const QPoint &location) { Q_D(WebContentsAdapter); if (content::DevToolsAgentHost::HasFor(d->webContents.get())) { - content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->InspectElement(location.x(), location.y()); + content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->InspectElement(nullptr, location.x(), location.y()); } } @@ -956,19 +1010,28 @@ void WebContentsAdapter::wasHidden() void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString &filePath) { #if defined(ENABLE_BASIC_PRINTING) - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDF(pageLayout, true, filePath); + Q_D(WebContentsAdapter); + PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished, + d->adapterClient, + filePath); + PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFFileWithCallback(pageLayout, + true, + filePath, + callback); #endif // if defined(ENABLE_BASIC_PRINTING) } -quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout, const bool colorMode) +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, colorMode - , callback); + PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, + d->adapterClient, + d->nextRequestId); + PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, + colorMode, + callback); return d->nextRequestId++; #else return 0; @@ -1348,4 +1411,15 @@ bool WebContentsAdapter::canViewSource() return d->webContents->GetController().CanViewSource(); } +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UnknownDisposition, WindowOpenDisposition::UNKNOWN) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::CurrentTabDisposition, WindowOpenDisposition::CURRENT_TAB) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::SingletonTabDisposition, WindowOpenDisposition::SINGLETON_TAB) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewForegroundTabDisposition, WindowOpenDisposition::NEW_FOREGROUND_TAB) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewBackgroundTabDisposition, WindowOpenDisposition::NEW_BACKGROUND_TAB) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewPopupDisposition, WindowOpenDisposition::NEW_POPUP) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewWindowDisposition, WindowOpenDisposition::NEW_WINDOW) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::SaveToDiskDisposition, WindowOpenDisposition::SAVE_TO_DISK) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::OffTheRecordDisposition, WindowOpenDisposition::OFF_THE_RECORD) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::IgnoreActionDisposition, WindowOpenDisposition::IGNORE_ACTION) + } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 803b1eb57..10c65a6cb 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -42,6 +42,7 @@ #include "qtwebenginecoreglobal.h" #include "web_contents_adapter_client.h" +#include <QtWebEngineCore/qwebenginehttprequest.h> #include <QScopedPointer> #include <QSharedPointer> @@ -83,7 +84,8 @@ public: void stop(); void reload(); void reloadAndBypassCache(); - void load(const QUrl&); + void load(const QUrl &url); + void load(const QWebEngineHttpRequest &request); void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl); void save(const QString &filePath = QString(), int savePageFormat = -1); QUrl activeUrl() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 4e15df753..d4b2974fc 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -254,16 +254,15 @@ public: // This must match window_open_disposition_list.h. enum WindowOpenDisposition { UnknownDisposition = 0, - SuppressOpenDisposition = 1, - CurrentTabDisposition = 2, - SingletonTabDisposition = 3, - NewForegroundTabDisposition = 4, - NewBackgroundTabDisposition = 5, - NewPopupDisposition = 6, - NewWindowDisposition = 7, - SaveToDiskDisposition = 8, - OffTheRecordDisposition = 9, - IgnoreActionDisposition = 10, + CurrentTabDisposition = 1, + SingletonTabDisposition = 2, + NewForegroundTabDisposition = 3, + NewBackgroundTabDisposition = 4, + NewPopupDisposition = 5, + NewWindowDisposition = 6, + SaveToDiskDisposition = 7, + OffTheRecordDisposition = 8, + IgnoreActionDisposition = 9, }; // Must match the values in javascript_message_type.h. @@ -347,6 +346,7 @@ 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; + virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0; 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 83fed35a0..fb32ea813 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -101,7 +101,7 @@ WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms) { content::WebContents *target = source; - if (params.disposition != CURRENT_TAB) { + if (params.disposition != WindowOpenDisposition::CURRENT_TAB) { QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); if (targetAdapter) target = targetAdapter->webContents(); diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 24c4e198f..a8c6cca70 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -232,4 +232,11 @@ void WebContentsViewQt::TakeFocus(bool reverse) m_client->passOnFocus(reverse); } +void WebContentsViewQt::GetScreenInfo(content::ScreenInfo* results) const +{ + if (auto rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) + rwhv->GetScreenInfo(results); +} + + } // namespace QtWebEngineCore diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 48532c0c5..8d7d7a032 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -117,6 +117,8 @@ public: virtual void TakeFocus(bool reverse) Q_DECL_OVERRIDE; + virtual void GetScreenInfo(content::ScreenInfo* results) const Q_DECL_OVERRIDE; + #if defined(OS_MACOSX) virtual void SetAllowOtherViews(bool allow) Q_DECL_OVERRIDE { m_allowOtherViews = allow; } virtual bool GetAllowOtherViews() const Q_DECL_OVERRIDE { return m_allowOtherViews; } diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index b53234b45..78c0fa3b8 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -51,7 +51,7 @@ #if defined(ENABLE_BASIC_PRINTING) #include "chrome/browser/printing/print_job_manager.h" #endif // defined(ENABLE_BASIC_PRINTING) -#include "components/devtools_http_handler/devtools_http_handler.h" +#include "content/browser/devtools/devtools_http_handler.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/utility_process_host_impl.h" @@ -185,13 +185,15 @@ void WebEngineContext::destroyBrowserContext() void WebEngineContext::destroy() { + if (m_devtoolsServer) + m_devtoolsServer->stop(); delete m_globalQObject; m_globalQObject = 0; base::MessagePump::Delegate *delegate = m_runLoop->loop_; // Flush the UI message loop before quitting. while (delegate->DoWork()) { } GLContextHelper::destroy(); - m_devtools.reset(0); + m_devtoolsServer.reset(0); m_runLoop->AfterRun(); // Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner. @@ -207,7 +209,7 @@ WebEngineContext::~WebEngineContext() { // WebEngineContext::destroy() must be called before we are deleted Q_ASSERT(!m_globalQObject); - Q_ASSERT(!m_devtools); + Q_ASSERT(!m_devtoolsServer); Q_ASSERT(!m_browserRunner); } @@ -406,7 +408,8 @@ WebEngineContext::WebEngineContext() m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); - m_devtools = createDevToolsHttpHandler(); + m_devtoolsServer.reset(new DevToolsServerQt()); + m_devtoolsServer->start(); // Force the initialization of MediaCaptureDevicesDispatcher on the UI // thread to avoid a thread check assertion in its constructor when it // first gets referenced on the IO thread. diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 878b651de..0058ccd84 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -56,10 +56,6 @@ class BrowserMainRunner; class ContentMainRunner; } -namespace devtools_http_handler { -class DevToolsHttpHandler; -} - #if defined(ENABLE_BASIC_PRINTING) namespace printing { class PrintJobManager; @@ -72,6 +68,7 @@ namespace QtWebEngineCore { class BrowserContextAdapter; class ContentMainDelegateQt; +class DevToolsServerQt; class SurfaceFactoryQt; class WebEngineContext : public base::RefCounted<WebEngineContext> { @@ -97,7 +94,7 @@ private: std::unique_ptr<content::BrowserMainRunner> m_browserRunner; QObject* m_globalQObject; QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext; - std::unique_ptr<devtools_http_handler::DevToolsHttpHandler> m_devtools; + std::unique_ptr<DevToolsServerQt> m_devtoolsServer; #if defined(ENABLE_BASIC_PRINTING) std::unique_ptr<printing::PrintJobManager> m_printJobManager; #endif // defined(ENABLE_BASIC_PRINTING) diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 2e0669d4e..58f0a3e2c 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -242,6 +242,7 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(FocusOnNavigationEnabled, true); s_defaultAttributes.insert(PrintElementBackgrounds, true); s_defaultAttributes.insert(AllowRunningInsecureContent, allowRunningInsecureContent); + s_defaultAttributes.insert(AllowGeolocationOnInsecureOrigins, false); } if (offTheRecord) m_attributes.insert(LocalStorageEnabled, false); @@ -325,6 +326,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->experimental_webgl_enabled = testAttribute(WebGLEnabled); prefs->should_print_backgrounds = testAttribute(PrintElementBackgrounds); prefs->allow_running_insecure_content = testAttribute(AllowRunningInsecureContent); + prefs->allow_geolocation_on_insecure_origins = testAttribute(AllowGeolocationOnInsecureOrigins); // Fonts settings. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 8459ba75b..4b0ce7b39 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -82,7 +82,8 @@ public: TouchIconsEnabled, FocusOnNavigationEnabled, PrintElementBackgrounds, - AllowRunningInsecureContent + AllowRunningInsecureContent, + AllowGeolocationOnInsecureOrigins }; // Must match the values from the public API in qwebenginesettings.h. diff --git a/src/core/web_engine_visited_links_manager.cpp b/src/core/web_engine_visited_links_manager.cpp index 0cf76d456..689c130e6 100644 --- a/src/core/web_engine_visited_links_manager.cpp +++ b/src/core/web_engine_visited_links_manager.cpp @@ -44,6 +44,7 @@ #include "content_browser_client_qt.h" #include "type_conversion.h" +#include <base/files/file_util.h> #include "components/visitedlink/browser/visitedlink_delegate.h" #include "components/visitedlink/browser/visitedlink_master.h" @@ -90,11 +91,28 @@ bool WebEngineVisitedLinksManager::containsUrl(const QUrl &url) const return m_visitedLinkMaster->IsVisited(toGurl(url)); } +static void ensureDirectoryExists(const base::FilePath &path) +{ + if (base::PathExists(path)) + return; + + base::File::Error error; + if (base::CreateDirectoryAndGetError(path, &error)) + return; + + std::string errorstr = base::File::ErrorToString(error); + qWarning("Cannot create directory %s. Error: %s.", + path.AsUTF8Unsafe().c_str(), + errorstr.c_str()); +} + WebEngineVisitedLinksManager::WebEngineVisitedLinksManager(BrowserContextAdapter *adapter) : m_delegate(new VisitedLinkDelegateQt) { Q_ASSERT(adapter && adapter->browserContext()); BrowserContextQt *browserContext = adapter->browserContext(); + if (adapter->persistVisitedLinks()) + ensureDirectoryExists(browserContext->GetPath()); m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(browserContext, m_delegate.data(), adapter->persistVisitedLinks())); m_visitedLinkMaster->Init(); } diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 9681ad629..ff5cc99a8 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1036,25 +1036,25 @@ static inline double currentTimeForEvent(const QInputEvent* event) static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) - return WebMouseEvent::ButtonLeft; + return WebMouseEvent::Button::Left; else if (event->button() == Qt::RightButton) - return WebMouseEvent::ButtonRight; + return WebMouseEvent::Button::Right; else if (event->button() == Qt::MidButton) - return WebMouseEvent::ButtonMiddle; + return WebMouseEvent::Button::Middle; if (event->type() != QEvent::MouseMove) - return WebMouseEvent::ButtonNone; + return WebMouseEvent::Button::NoButton; // This is technically wrong, mouse move should always have ButtonNone, // but it is consistent with aura and selection code depends on it: if (event->buttons() & Qt::LeftButton) - return WebMouseEvent::ButtonLeft; + return WebMouseEvent::Button::Left; else if (event->buttons() & Qt::RightButton) - return WebMouseEvent::ButtonRight; + return WebMouseEvent::Button::Right; else if (event->buttons() & Qt::MidButton) - return WebMouseEvent::ButtonMiddle; + return WebMouseEvent::Button::Middle; - return WebMouseEvent::ButtonNone; + return WebMouseEvent::Button::NoButton; } template <typename T> @@ -1247,7 +1247,6 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e webKitEvent.nativeKeyCode = ev->nativeVirtualKey(); webKitEvent.windowsKeyCode = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); - webKitEvent.setKeyIdentifierFromWindowsKeyCode(); webKitEvent.domKey = getDomKeyFromQKeyEvent(ev); ui::DomCode domCode = ui::DomCode::NONE; diff --git a/src/src.pro b/src/src.pro index 9b5373181..d9b57615d 100644 --- a/src/src.pro +++ b/src/src.pro @@ -7,14 +7,17 @@ webengine_plugin.subdir = webengine/plugin webengine_plugin.target = sub-webengine-plugin webengine_plugin.depends = webengine -SUBDIRS += core \ +core.depends = buildtools + +SUBDIRS += buildtools \ + core \ process \ webengine \ webengine_plugin \ plugins -# allow only desktop builds of qwebengine_convert_dict -contains(WEBENGINE_CONFIG, use_spellchecker):!contains(WEBENGINE_CONFIG, use_native_spellchecker):!cross_compile { + +use?(spellchecker):!use?(native_spellchecker):!cross_compile { SUBDIRS += qwebengine_convert_dict qwebengine_convert_dict.subdir = tools/qwebengine_convert_dict qwebengine_convert_dict.depends = core @@ -27,13 +30,12 @@ isQMLTestSupportApiEnabled() { SUBDIRS += webengine_testsupport_plugin } -# FIXME: We probably want a bit more control over config options to tweak what to build/ship or not. -# Another example of where this could be necessary is to make it easy to build proprietery codecs support. !contains(WEBENGINE_CONFIG, no_ui_delegates) { SUBDIRS += webengine/ui \ webengine/ui2 } + qtHaveModule(widgets) { - SUBDIRS += webenginewidgets - plugins.depends = webenginewidgets + SUBDIRS += webenginewidgets + plugins.depends = webenginewidgets } diff --git a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro index f2dbb12cf..2bdfee304 100644 --- a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro +++ b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro @@ -1,12 +1,36 @@ option(host_build) # Look for linking information produced by gyp for our target according to core_generated.gyp -!include($$OUT_PWD/../../core/$$getConfigDir()/convert_dict_linking.pri) { - error("Could not find the linking information that gyp should have generated.") +use?(gn): linking_pri = $$OUT_PWD/../../core/$$getConfigDir()/convert_dict.pri +else: linking_pri = $$OUT_PWD/../../core/$$getConfigDir()/convert_dict_linking.pri + +!include($$linking_pri) { + error("Could not find the linking information that gyp/gn should have generated.") +} + +use?(gn){ + isEmpty(NINJA_OBJECTS): error("Missing object files from QtWebEngineCore linking pri.") + isEmpty(NINJA_LFLAGS): error("Missing linker flags from QtWebEngineCore linking pri") + isEmpty(NINJA_ARCHIVES): error("Missing archive files from QtWebEngineCore linking pri") + isEmpty(NINJA_LIBS): error("Missing library files from QtWebEngineCore linking pri") + OBJECTS = $$eval($$list($$NINJA_OBJECTS)) + linux { + LIBS_PRIVATE = -Wl,--start-group $$NINJA_ARCHIVES -Wl,--end-group + } else { + LIBS_PRIVATE = $$NINJA_ARCHIVES + } + LIBS_PRIVATE += $$NINJA_LIB_DIRS $$NINJA_LIBS + QMAKE_LFLAGS += $$NINJA_LFLAGS + POST_TARGETDEPS += $$NINJA_TARGETDEPS +} else { + # skip dummy main.cpp file + OBJECTS = } -# skip dummy main.cpp file -OBJECTS = +#ninja compiles with std::__debug +use?(gn): linux: CONFIG(debug, debug|release) { + DEFINES += _GLIBCXX_DEBUG +} # Fixme: -Werror=unused-parameter in core QMAKE_CXXFLAGS_WARN_ON = diff --git a/src/webengine/api/qquickwebenginecertificateerror_p.h b/src/webengine/api/qquickwebenginecertificateerror_p.h index 27b2efa14..77fbe27aa 100644 --- a/src/webengine/api/qquickwebenginecertificateerror_p.h +++ b/src/webengine/api/qquickwebenginecertificateerror_p.h @@ -61,10 +61,10 @@ class CertificateErrorController; class Q_WEBENGINE_EXPORT QQuickWebEngineCertificateError : public QObject { Q_OBJECT - Q_PROPERTY(QUrl url READ url) - Q_PROPERTY(Error error READ error) - Q_PROPERTY(QString description READ description) - Q_PROPERTY(bool overridable READ overridable) + Q_PROPERTY(QUrl url READ url CONSTANT FINAL) + Q_PROPERTY(Error error READ error CONSTANT FINAL) + Q_PROPERTY(QString description READ description CONSTANT FINAL) + Q_PROPERTY(bool overridable READ overridable CONSTANT FINAL) public: diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index 03058fdb3..ac320a9e6 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -45,6 +45,34 @@ using QtWebEngineCore::BrowserContextAdapterClient; QT_BEGIN_NAMESPACE +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NoReason, QQuickWebEngineDownloadItem::NoReason) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileFailed, QQuickWebEngineDownloadItem::FileFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileAccessDenied, QQuickWebEngineDownloadItem::FileAccessDenied) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileNoSpace, QQuickWebEngineDownloadItem::FileNoSpace) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileNameTooLong, QQuickWebEngineDownloadItem::FileNameTooLong) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTooLarge, QQuickWebEngineDownloadItem::FileTooLarge) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileVirusInfected, QQuickWebEngineDownloadItem::FileVirusInfected) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTransientError, QQuickWebEngineDownloadItem::FileTransientError) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileBlocked, QQuickWebEngineDownloadItem::FileBlocked) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileSecurityCheckFailed, QQuickWebEngineDownloadItem::FileSecurityCheckFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTooShort, QQuickWebEngineDownloadItem::FileTooShort) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileHashMismatch, QQuickWebEngineDownloadItem::FileHashMismatch) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkFailed, QQuickWebEngineDownloadItem::NetworkFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkTimeout, QQuickWebEngineDownloadItem::NetworkTimeout) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkDisconnected, QQuickWebEngineDownloadItem::NetworkDisconnected) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkServerDown, QQuickWebEngineDownloadItem::NetworkServerDown) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkInvalidRequest, QQuickWebEngineDownloadItem::NetworkInvalidRequest) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerFailed, QQuickWebEngineDownloadItem::ServerFailed) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerNoRange, QQuickWebEngineDownloadItem::ServerNoRange) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerBadContent, QQuickWebEngineDownloadItem::ServerBadContent) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerUnauthorized, QQuickWebEngineDownloadItem::ServerUnauthorized) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerCertProblem, QQuickWebEngineDownloadItem::ServerCertProblem) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerForbidden, QQuickWebEngineDownloadItem::ServerForbidden) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerUnreachable, QQuickWebEngineDownloadItem::ServerUnreachable) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::UserCanceled, QQuickWebEngineDownloadItem::UserCanceled) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::UserShutdown, QQuickWebEngineDownloadItem::UserShutdown) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::Crash, QQuickWebEngineDownloadItem::Crash) + static inline QQuickWebEngineDownloadItem::DownloadState toDownloadState(int state) { switch (state) { case BrowserContextAdapterClient::DownloadInProgress: @@ -61,12 +89,18 @@ static inline QQuickWebEngineDownloadItem::DownloadState toDownloadState(int sta } } +static inline QQuickWebEngineDownloadItem::DownloadInterruptReason toDownloadInterruptReason(int reason) +{ + return static_cast<QQuickWebEngineDownloadItem::DownloadInterruptReason>(reason); +} + QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfile *p) : profile(p) , downloadId(-1) , downloadState(QQuickWebEngineDownloadItem::DownloadCancelled) , savePageFormat(QQuickWebEngineDownloadItem::UnknownSaveFormat) , type(QQuickWebEngineDownloadItem::Attachment) + , interruptReason(QQuickWebEngineDownloadItem::NoReason) , totalBytes(-1) , receivedBytes(0) { @@ -97,6 +131,11 @@ void QQuickWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClien updateState(toDownloadState(info.state)); + if (toDownloadInterruptReason(info.downloadInterruptReason) != interruptReason) { + interruptReason = toDownloadInterruptReason(info.downloadInterruptReason); + Q_EMIT q->interruptReasonChanged(); + } + if (info.receivedBytes != receivedBytes) { receivedBytes = info.receivedBytes; Q_EMIT q->receivedBytesChanged(); @@ -326,6 +365,67 @@ QQuickWebEngineDownloadItem::DownloadType QQuickWebEngineDownloadItem::type() co return d->type; } +/*! + \qmlproperty enumeration WebEngineDownloadItem::interruptReason + \readonly + \since QtWebEngine 1.6 + + Returns the reason why the download was interrupted: + + \value WebEngineDownloadItem.NoReason Unknown reason or not interrupted. + \value WebEngineDownloadItem.FileFailed General file operation failure. + \value WebEngineDownloadItem.FileAccessDenied The file cannot be written locally, due to access restrictions. + \value WebEngineDownloadItem.FileNoSpace Insufficient space on the target drive. + \value WebEngineDownloadItem.FileNameTooLong The directory or file name is too long. + \value WebEngineDownloadItem.FileTooLarge The file size exceeds the file system limitation. + \value WebEngineDownloadItem.FileVirusInfected The file is infected with a virus. + \value WebEngineDownloadItem.FileTransientError Temporary problem (for example the file is in use, + out of memory, or too many files are opened at once). + \value WebEngineDownloadItem.FileBlocked The file was blocked due to local policy. + \value WebEngineDownloadItem.FileSecurityCheckFailed An attempt to check the safety of the download + failed due to unexpected reasons. + \value WebEngineDownloadItem.FileTooShort An attempt was made to seek past the end of a file when + opening a file (as part of resuming a previously interrupted download). + \value WebEngineDownloadItem.FileHashMismatch The partial file did not match the expected hash. + + \value WebEngineDownloadItem.NetworkFailed General network failure. + \value WebEngineDownloadItem.NetworkTimeout The network operation has timed out. + \value WebEngineDownloadItem.NetworkDisconnected The network connection has been terminated. + \value WebEngineDownloadItem.NetworkServerDown The server has gone down. + \value WebEngineDownloadItem.NetworkInvalidRequest The network request was invalid (for example, the + original or redirected URL is invalid, has an unsupported scheme, or is disallowed by policy). + + \value WebEngineDownloadItem.ServerFailed General server failure. + \value WebEngineDownloadItem.ServerBadContent The server does not have the requested data. + \value WebEngineDownloadItem.ServerUnauthorized The server did not authorize access to the resource. + \value WebEngineDownloadItem.ServerCertProblem A problem with the server certificate occurred. + \value WebEngineDownloadItem.ServerForbidden Access forbidden by the server. + \value WebEngineDownloadItem.ServerUnreachable Unexpected server response (might indicate that + the responding server may not be the intended server). + \value WebEngineDownloadItem.UserCanceled The user canceled the download. + + \sa interruptReasonString() +*/ + +QQuickWebEngineDownloadItem::DownloadInterruptReason QQuickWebEngineDownloadItem::interruptReason() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->interruptReason; +} + +/*! + Returns a human-readable description of the reason for interrupting the download. + \since QtWebEngine 1.6 + + \sa interruptReason() +*/ + +QString QQuickWebEngineDownloadItem::interruptReasonString() const +{ + return BrowserContextAdapterClient::downloadInterruptReasonToString( + static_cast<BrowserContextAdapterClient::DownloadInterruptReason>(interruptReason())); +} + QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h index 61e019b9e..889d0bcb7 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p.h @@ -82,6 +82,37 @@ public: }; Q_ENUM(SavePageFormat) + enum DownloadInterruptReason { + NoReason = 0, + FileFailed = 1, + FileAccessDenied = 2, + FileNoSpace = 3, + FileNameTooLong = 5, + FileTooLarge = 6, + FileVirusInfected = 7, + FileTransientError = 10, + FileBlocked = 11, + FileSecurityCheckFailed = 12, + FileTooShort = 13, + FileHashMismatch = 14, + NetworkFailed = 20, + NetworkTimeout = 21, + NetworkDisconnected = 22, + NetworkServerDown = 23, + NetworkInvalidRequest = 24, + ServerFailed = 30, + //ServerNoRange = 31, + ServerBadContent = 33, + ServerUnauthorized = 34, + ServerCertProblem = 35, + ServerForbidden = 36, + ServerUnreachable = 37, + UserCanceled = 40, + //UserShutdown = 41, + //Crash = 50 + }; + Q_ENUM(DownloadInterruptReason) + enum DownloadType { Attachment = 0, DownloadAttribute, @@ -91,13 +122,15 @@ public: Q_ENUM(DownloadType) Q_PROPERTY(quint32 id READ id CONSTANT FINAL) - Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged) + Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged FINAL) Q_PROPERTY(SavePageFormat savePageFormat READ savePageFormat WRITE setSavePageFormat NOTIFY savePageFormatChanged REVISION 2 FINAL) - Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged) - Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged) - Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged REVISION 1) - Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) + Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged FINAL) + Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged FINAL) + Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged REVISION 1 FINAL) + Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL) Q_PROPERTY(DownloadType type READ type NOTIFY typeChanged REVISION 3 FINAL) + Q_PROPERTY(DownloadInterruptReason interruptReason READ interruptReason NOTIFY interruptReasonChanged REVISION 4 FINAL) + Q_PROPERTY(QString interruptReasonString READ interruptReasonString NOTIFY interruptReasonChanged REVISION 4 FINAL) Q_INVOKABLE void accept(); Q_INVOKABLE void cancel(); @@ -112,6 +145,8 @@ public: SavePageFormat savePageFormat() const; void setSavePageFormat(SavePageFormat format); DownloadType type() const; + DownloadInterruptReason interruptReason() const; + QString interruptReasonString() const; Q_SIGNALS: void stateChanged(); @@ -121,6 +156,7 @@ Q_SIGNALS: Q_REVISION(1) void mimeTypeChanged(); void pathChanged(); Q_REVISION(3) void typeChanged(); + Q_REVISION(4) void interruptReasonChanged(); private: QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate*, QObject *parent = 0); diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h index 1789af462..4fb609492 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h @@ -74,6 +74,7 @@ public: QQuickWebEngineDownloadItem::DownloadState downloadState; QQuickWebEngineDownloadItem::SavePageFormat savePageFormat; QQuickWebEngineDownloadItem::DownloadType type; + QQuickWebEngineDownloadItem::DownloadInterruptReason interruptReason; qint64 totalBytes; qint64 receivedBytes; QString mimeType; diff --git a/src/webengine/api/qquickwebengineloadrequest_p.h b/src/webengine/api/qquickwebengineloadrequest_p.h index a50ffc42a..aa4bc906c 100644 --- a/src/webengine/api/qquickwebengineloadrequest_p.h +++ b/src/webengine/api/qquickwebengineloadrequest_p.h @@ -60,11 +60,11 @@ class QQuickWebEngineLoadRequestPrivate; class Q_WEBENGINE_EXPORT QQuickWebEngineLoadRequest : public QObject { Q_OBJECT - Q_PROPERTY(QUrl url READ url) - Q_PROPERTY(QQuickWebEngineView::LoadStatus status READ status) - Q_PROPERTY(QString errorString READ errorString) - Q_PROPERTY(QQuickWebEngineView::ErrorDomain errorDomain READ errorDomain) - Q_PROPERTY(int errorCode READ errorCode) + Q_PROPERTY(QUrl url READ url CONSTANT FINAL) + Q_PROPERTY(QQuickWebEngineView::LoadStatus status READ status CONSTANT FINAL) + Q_PROPERTY(QString errorString READ errorString CONSTANT FINAL) + Q_PROPERTY(QQuickWebEngineView::ErrorDomain errorDomain READ errorDomain CONSTANT FINAL) + Q_PROPERTY(int errorCode READ errorCode CONSTANT FINAL) public: QQuickWebEngineLoadRequest(const QUrl& url, QQuickWebEngineView::LoadStatus status, const QString& errorString = QString(), int errorCode = 0, QQuickWebEngineView::ErrorDomain errorDomain = QQuickWebEngineView::NoErrorDomain, QObject* parent = 0); diff --git a/src/webengine/api/qquickwebenginenewviewrequest.cpp b/src/webengine/api/qquickwebenginenewviewrequest.cpp index 36df9023a..e0307ad41 100644 --- a/src/webengine/api/qquickwebenginenewviewrequest.cpp +++ b/src/webengine/api/qquickwebenginenewviewrequest.cpp @@ -72,6 +72,16 @@ QQuickWebEngineView::NewViewDestination QQuickWebEngineNewViewRequest::destinati } /*! + \qmlproperty QUrl WebEngineNewViewRequest::requestedUrl + The URL that is requested by the page. + \since QtWebEngine 1.6 + */ +QUrl QQuickWebEngineNewViewRequest::requestedUrl() const +{ + return m_requestedUrl; +} + +/*! \qmlproperty bool WebEngineNewViewRequest::userInitiated Whether this window request was directly triggered as the result of a keyboard or mouse event. diff --git a/src/webengine/api/qquickwebenginenewviewrequest_p.h b/src/webengine/api/qquickwebenginenewviewrequest_p.h index fd7fc42f4..9cc0f291f 100644 --- a/src/webengine/api/qquickwebenginenewviewrequest_p.h +++ b/src/webengine/api/qquickwebenginenewviewrequest_p.h @@ -63,11 +63,13 @@ QT_BEGIN_NAMESPACE class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineNewViewRequest : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebEngineView::NewViewDestination destination READ destination CONSTANT FINAL) + Q_PROPERTY(QUrl requestedUrl READ requestedUrl CONSTANT REVISION 1 FINAL) Q_PROPERTY(bool userInitiated READ isUserInitiated CONSTANT FINAL) public: ~QQuickWebEngineNewViewRequest(); QQuickWebEngineView::NewViewDestination destination() const; + QUrl requestedUrl() const; bool isUserInitiated() const; Q_INVOKABLE void openIn(QQuickWebEngineView *view); diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index 35efcb3b4..f22ec86a4 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -42,6 +42,7 @@ #include "qquickwebenginedownloaditem_p.h" #include "qquickwebenginedownloaditem_p_p.h" #include "qquickwebengineprofile_p.h" +#include "qquickwebenginescript_p.h" #include "qquickwebenginesettings_p.h" #include "qwebenginecookiestore.h" @@ -49,6 +50,7 @@ #include "browser_context_adapter.h" #include <qtwebenginecoreglobal.h> +#include "renderer_host/user_resource_controller_host.h" #include "web_engine_settings.h" using QtWebEngineCore::BrowserContextAdapter; @@ -229,6 +231,38 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info } } +void QQuickWebEngineProfilePrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script) +{ + Q_ASSERT(p && p->data); + QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data); + QtWebEngineCore::UserResourceControllerHost *resourceController = d->browserContext()->userResourceController(); + d->m_userScripts.append(script); + script->d_func()->bind(resourceController); +} + +int QQuickWebEngineProfilePrivate::userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p) +{ + Q_ASSERT(p && p->data); + QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data); + return d->m_userScripts.count(); +} + +QQuickWebEngineScript *QQuickWebEngineProfilePrivate::userScripts_at(QQmlListProperty<QQuickWebEngineScript> *p, int idx) +{ + Q_ASSERT(p && p->data); + QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data); + return d->m_userScripts.at(idx); +} + +void QQuickWebEngineProfilePrivate::userScripts_clear(QQmlListProperty<QQuickWebEngineScript> *p) +{ + Q_ASSERT(p && p->data); + QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data); + QtWebEngineCore::UserResourceControllerHost *resourceController = d->browserContext()->userResourceController(); + resourceController->clearAllScripts(NULL); + d->m_userScripts.clear(); +} + /*! \qmltype WebEngineProfile \instantiates QQuickWebEngineProfile @@ -851,4 +885,33 @@ QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const return d->settings(); } +/*! + \qmlproperty list<WebEngineScript> WebEngineProfile::userScripts + \since 1.5 + + Returns the collection of WebEngineScripts that are injected into all pages that share + this profile. + + \sa WebEngineScript +*/ + +/*! + \property QQuickWebEngineProfile::userScripts + \since 5.9 + + \brief the collection of scripts that are injected into all pages that share + this profile. + + \sa QQuickWebEngineScript, QQmlListReference +*/ +QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineProfile::userScripts() +{ + Q_D(QQuickWebEngineProfile); + return QQmlListProperty<QQuickWebEngineScript>(this, d, + d->userScripts_append, + d->userScripts_count, + d->userScripts_at, + d->userScripts_clear); +} + QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h index d0d925930..0155c954a 100644 --- a/src/webengine/api/qquickwebengineprofile.h +++ b/src/webengine/api/qquickwebengineprofile.h @@ -46,6 +46,7 @@ #include <QtCore/QObject> #include <QtCore/QScopedPointer> #include <QtCore/QString> +#include <QtQml/QQmlListProperty> namespace QtWebEngineCore { class BrowserContextAdapter; @@ -55,6 +56,7 @@ QT_BEGIN_NAMESPACE class QQuickWebEngineDownloadItem; class QQuickWebEngineProfilePrivate; +class QQuickWebEngineScript; class QQuickWebEngineSettings; class QWebEngineCookieStore; class QWebEngineUrlRequestInterceptor; @@ -73,6 +75,7 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject { Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL) Q_PROPERTY(QStringList spellCheckLanguages READ spellCheckLanguages WRITE setSpellCheckLanguages NOTIFY spellCheckLanguagesChanged FINAL REVISION 3) Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION 3) + Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 4) public: QQuickWebEngineProfile(QObject *parent = Q_NULLPTR); @@ -136,6 +139,8 @@ public: void setSpellCheckEnabled(bool enabled); bool isSpellCheckEnabled() const; + QQmlListProperty<QQuickWebEngineScript> userScripts(); + static QQuickWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index 1ba1eb53f..1828f8085 100644 --- a/src/webengine/api/qquickwebengineprofile_p.h +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -80,12 +80,19 @@ public: void downloadRequested(DownloadItemInfo &info) Q_DECL_OVERRIDE; void downloadUpdated(const DownloadItemInfo &info) Q_DECL_OVERRIDE; + // QQmlListPropertyHelpers + static void userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script); + static int userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p); + static QQuickWebEngineScript *userScripts_at(QQmlListProperty<QQuickWebEngineScript> *p, int idx); + static void userScripts_clear(QQmlListProperty<QQuickWebEngineScript> *p); + private: friend class QQuickWebEngineViewPrivate; QQuickWebEngineProfile *q_ptr; QScopedPointer<QQuickWebEngineSettings> m_settings; QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef; QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads; + QList<QQuickWebEngineScript *> m_userScripts; }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginescript.cpp b/src/webengine/api/qquickwebenginescript.cpp index 5d5173144..590faf4f3 100644 --- a/src/webengine/api/qquickwebenginescript.cpp +++ b/src/webengine/api/qquickwebenginescript.cpp @@ -37,8 +37,8 @@ ** ****************************************************************************/ +#include "qquickwebenginescript.h" #include "qquickwebenginescript_p.h" -#include "qquickwebenginescript_p_p.h" #include <QQmlFile> #include <QtCore/QDebug> @@ -48,6 +48,58 @@ using QtWebEngineCore::UserScript; +QT_BEGIN_NAMESPACE + +/*! + \class QQuickWebEngineScript + \brief Enables the injection of scripts in the JavaScript engine. + \inmodule QtWebEngine + \since 5.9 + + The QQuickWebEngineScript type enables the programmatic injection of so called \e {user scripts} in + the JavaScript engine at different points, determined by injectionPoint, during the loading of + web content. + + Scripts can be executed either in the main JavaScript \e world, along with the rest of the + JavaScript coming from the web contents, or in their own isolated world. While the DOM of the + page can be accessed from any world, JavaScript variables of a function defined in one world are + not accessible from a different one. The worldId property provides some predefined IDs for this + purpose. +*/ + +/*! + \enum QQuickWebEngineScript::InjectionPoint + + The point in the loading process at which the script will be executed. + + \value DocumentCreation + The script will be executed as soon as the document is created. This is not suitable for + any DOM operation. + \value DocumentReady + The script will run as soon as the DOM is ready. This is equivalent to the + \c DOMContentLoaded event firing in JavaScript. + \value Deferred + The script will run when the page load finishes, or 500 ms after the document is ready, + whichever comes first. +*/ + +/*! + \enum QQuickWebEngineScript::ScriptWorldId + + The world ID defining which isolated world the script is executed in. + + \value MainWorld + The world used by the page's web contents. It can be useful in order to expose custom + functionality to web contents in certain scenarios. + \value ApplicationWorld + The default isolated world used for application level functionality implemented in + JavaScript. + \value UserWorld + The first isolated world to be used by scripts set by users if the application is not + making use of more worlds. As a rule of thumb, if that functionality is exposed to the + application users, each individual script should probably get its own isolated world. +*/ + /*! \qmltype WebEngineScript \instantiates QQuickWebEngineScript @@ -72,16 +124,26 @@ using QtWebEngineCore::UserScript; attached to the web view. */ -QQuickWebEngineScript::QQuickWebEngineScript() - : d_ptr(new QQuickWebEngineScriptPrivate) +/*! + Constructs a new QQuickWebEngineScript with the parent \a parent. +*/ +QQuickWebEngineScript::QQuickWebEngineScript(QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineScriptPrivate) { d_ptr->q_ptr = this; } +/*! + \internal +*/ QQuickWebEngineScript::~QQuickWebEngineScript() { } +/*! + Returns the script object as string. +*/ QString QQuickWebEngineScript::toString() const { Q_D(const QQuickWebEngineScript); @@ -106,6 +168,14 @@ QString QQuickWebEngineScript::toString() const } /*! + \property QQuickWebEngineScript::name + \brief The name of the script. + + Can be useful to retrieve a particular script from + QQuickWebEngineProfile::userScripts. +*/ + +/*! \qmlproperty string WebEngineScript::name The name of the script. Can be useful to retrieve a particular script from @@ -118,6 +188,20 @@ QString QQuickWebEngineScript::name() const } /*! + \property QQuickWebEngineScript::sourceUrl + \brief The remote source location of the user script (if any). + + Unlike \l sourceCode, this property allows referring to user scripts that + are not already loaded in memory, for instance, when stored on disk. + + Setting this property will change the \l sourceCode of the script. + + \note At present, only file-based sources are supported. + + \sa QQuickWebEngineScript::sourceCode +*/ + +/*! \qmlproperty url WebEngineScript::sourceUrl This property holds the remote source location of the user script (if any). @@ -138,6 +222,13 @@ QUrl QQuickWebEngineScript::sourceUrl() const } /*! + \property QQuickWebEngineScript::sourceCode + \brief The JavaScript source code of the user script. + + \sa QQuickWebEngineScript::sourceUrl +*/ + +/*! \qmlproperty string WebEngineScript::sourceCode This property holds the JavaScript source code of the user script. @@ -155,6 +246,13 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineScript::DocumentReady, UserScript::DocumentLoa ASSERT_ENUMS_MATCH(QQuickWebEngineScript::DocumentCreation, UserScript::DocumentElementCreation) /*! + \property QQuickWebEngineScript::injectionPoint + \brief The point in the loading process at which the script will be executed. + + The default value is \c Deferred. +*/ + +/*! \qmlproperty enumeration WebEngineScript::injectionPoint The point in the loading process at which the script will be executed. @@ -177,6 +275,11 @@ QQuickWebEngineScript::InjectionPoint QQuickWebEngineScript::injectionPoint() co } /*! + \property QQuickWebEngineScript::worldId + \brief The world ID defining which isolated world the script is executed in. +*/ + +/*! \qmlproperty enumeration WebEngineScript::worldId The world ID defining which isolated world the script is executed in. @@ -199,6 +302,15 @@ QQuickWebEngineScript::ScriptWorldId QQuickWebEngineScript::worldId() const } /*! + \property QQuickWebEngineScript::runOnSubframes + \brief Whether the script is executed on every frame or only on the main frame. + + Set this property to \c true if the script is executed on every frame in the page, or \c false + if it is only run for the main frame. + The default value is \c{false}. +*/ + +/*! \qmlproperty int WebEngineScript::runOnSubframes Set this property to \c true if the script is executed on every frame in the page, or \c false @@ -211,21 +323,20 @@ bool QQuickWebEngineScript::runOnSubframes() const return d->coreScript.runsOnSubFrames(); } - -void QQuickWebEngineScript::setName(QString arg) +void QQuickWebEngineScript::setName(const QString &name) { Q_D(QQuickWebEngineScript); - if (arg == name()) + if (name == QQuickWebEngineScript::name()) return; d->aboutToUpdateUnderlyingScript(); - d->coreScript.setName(arg); - Q_EMIT nameChanged(arg); + d->coreScript.setName(name); + Q_EMIT nameChanged(name); } -void QQuickWebEngineScript::setSourceCode(QString arg) +void QQuickWebEngineScript::setSourceCode(const QString &code) { Q_D(QQuickWebEngineScript); - if (arg == sourceCode()) + if (code == sourceCode()) return; // setting the source directly resets the sourceUrl @@ -235,22 +346,22 @@ void QQuickWebEngineScript::setSourceCode(QString arg) } d->aboutToUpdateUnderlyingScript(); - d->coreScript.setSourceCode(arg); - Q_EMIT sourceCodeChanged(arg); + d->coreScript.setSourceCode(code); + Q_EMIT sourceCodeChanged(code); } -void QQuickWebEngineScript::setSourceUrl(QUrl arg) +void QQuickWebEngineScript::setSourceUrl(const QUrl &url) { Q_D(QQuickWebEngineScript); - if (arg == sourceUrl()) + if (url == sourceUrl()) return; - d->m_sourceUrl = arg; + d->m_sourceUrl = url; Q_EMIT sourceUrlChanged(d->m_sourceUrl); - QFile f(QQmlFile::urlToLocalFileOrQrc(arg)); + QFile f(QQmlFile::urlToLocalFileOrQrc(url)); if (!f.open(QIODevice::ReadOnly)) { - qWarning() << "Can't open user script " << arg; + qWarning() << "Can't open user script " << url; return; } @@ -260,36 +371,36 @@ void QQuickWebEngineScript::setSourceUrl(QUrl arg) Q_EMIT sourceCodeChanged(source); } -void QQuickWebEngineScript::setInjectionPoint(QQuickWebEngineScript::InjectionPoint arg) +void QQuickWebEngineScript::setInjectionPoint(QQuickWebEngineScript::InjectionPoint injectionPoint) { Q_D(QQuickWebEngineScript); - if (arg == injectionPoint()) + if (injectionPoint == QQuickWebEngineScript::injectionPoint()) return; d->aboutToUpdateUnderlyingScript(); - d->coreScript.setInjectionPoint(static_cast<UserScript::InjectionPoint>(arg)); - Q_EMIT injectionPointChanged(arg); + d->coreScript.setInjectionPoint(static_cast<UserScript::InjectionPoint>(injectionPoint)); + Q_EMIT injectionPointChanged(injectionPoint); } -void QQuickWebEngineScript::setWorldId(QQuickWebEngineScript::ScriptWorldId arg) +void QQuickWebEngineScript::setWorldId(QQuickWebEngineScript::ScriptWorldId scriptWorldId) { Q_D(QQuickWebEngineScript); - if (arg == worldId()) + if (scriptWorldId == worldId()) return; d->aboutToUpdateUnderlyingScript(); - d->coreScript.setWorldId(arg); - Q_EMIT worldIdChanged(arg); + d->coreScript.setWorldId(scriptWorldId); + Q_EMIT worldIdChanged(scriptWorldId); } -void QQuickWebEngineScript::setRunOnSubframes(bool arg) +void QQuickWebEngineScript::setRunOnSubframes(bool on) { Q_D(QQuickWebEngineScript); - if (arg == runOnSubframes()) + if (on == runOnSubframes()) return; d->aboutToUpdateUnderlyingScript(); - d->coreScript.setRunsOnSubFrames(arg); - Q_EMIT runOnSubframesChanged(arg); + d->coreScript.setRunsOnSubFrames(on); + Q_EMIT runOnSubframesChanged(on); } void QQuickWebEngineScript::timerEvent(QTimerEvent *e) @@ -327,3 +438,5 @@ void QQuickWebEngineScriptPrivate::aboutToUpdateUnderlyingScript() // Defer updates to the next event loop m_basicTimer.start(0, q); } + +QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginescript.h b/src/webengine/api/qquickwebenginescript.h new file mode 100644 index 000000000..0b28d4c55 --- /dev/null +++ b/src/webengine/api/qquickwebenginescript.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINESCRIPT_H +#define QQUICKWEBENGINESCRIPT_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtWebEngine/qtwebengineglobal.h> + +QT_BEGIN_NAMESPACE +class QQuickWebEngineScriptPrivate; +class QQuickWebEngineView; + +class Q_WEBENGINE_EXPORT QQuickWebEngineScript : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) + Q_PROPERTY(QUrl sourceUrl READ sourceUrl WRITE setSourceUrl NOTIFY sourceUrlChanged FINAL) + Q_PROPERTY(QString sourceCode READ sourceCode WRITE setSourceCode NOTIFY sourceCodeChanged FINAL) + Q_PROPERTY(InjectionPoint injectionPoint READ injectionPoint WRITE setInjectionPoint NOTIFY injectionPointChanged FINAL) + Q_PROPERTY(ScriptWorldId worldId READ worldId WRITE setWorldId NOTIFY worldIdChanged FINAL) + Q_PROPERTY(bool runOnSubframes READ runOnSubframes WRITE setRunOnSubframes NOTIFY runOnSubframesChanged FINAL) + + +public: + enum InjectionPoint { + Deferred, + DocumentReady, + DocumentCreation + }; + Q_ENUM(InjectionPoint) + + enum ScriptWorldId { + MainWorld = 0, + ApplicationWorld, + UserWorld + }; + Q_ENUM(ScriptWorldId) + + explicit QQuickWebEngineScript(QObject *parent = Q_NULLPTR); + ~QQuickWebEngineScript(); + Q_INVOKABLE QString toString() const; + + QString name() const; + QUrl sourceUrl() const; + QString sourceCode() const; + InjectionPoint injectionPoint() const; + ScriptWorldId worldId() const; + bool runOnSubframes() const; + + void setName(const QString &name); + void setSourceUrl(const QUrl &url); + void setSourceCode(const QString &code); + void setInjectionPoint(InjectionPoint injectionPoint); + void setWorldId(ScriptWorldId scriptWorldId); + void setRunOnSubframes(bool on); + +Q_SIGNALS: + void nameChanged(const QString &name); + void sourceUrlChanged(const QUrl &url); + void sourceCodeChanged(const QString &code); + void injectionPointChanged(InjectionPoint injectionPoint); + void worldIdChanged(ScriptWorldId scriptWorldId); + void runOnSubframesChanged(bool on); + +protected: + void timerEvent(QTimerEvent *e) override; + +private: + friend class QQuickWebEngineProfilePrivate; + friend class QQuickWebEngineViewPrivate; + Q_DECLARE_PRIVATE(QQuickWebEngineScript) + QScopedPointer<QQuickWebEngineScriptPrivate> d_ptr; +}; +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINESCRIPT_H diff --git a/src/webengine/api/qquickwebenginescript_p.h b/src/webengine/api/qquickwebenginescript_p.h index 2c3b87d9b..30b47a654 100644 --- a/src/webengine/api/qquickwebenginescript_p.h +++ b/src/webengine/api/qquickwebenginescript_p.h @@ -51,75 +51,37 @@ // We mean it. // -#include <private/qtwebengineglobal_p.h> -#include <QtCore/QObject> -#include <QtCore/QUrl> +#include "qquickwebenginescript.h" -QT_BEGIN_NAMESPACE -class QQuickWebEngineScriptPrivate; -class QQuickWebEngineView; +#include <QtCore/QBasicTimer> +#include "user_script.h" +#include "web_contents_adapter.h" -class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineScript : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) - Q_PROPERTY(QUrl sourceUrl READ sourceUrl WRITE setSourceUrl NOTIFY sourceUrlChanged) - Q_PROPERTY(QString sourceCode READ sourceCode WRITE setSourceCode NOTIFY sourceCodeChanged) - Q_PROPERTY(InjectionPoint injectionPoint READ injectionPoint WRITE setInjectionPoint NOTIFY injectionPointChanged) - Q_PROPERTY(ScriptWorldId worldId READ worldId WRITE setWorldId NOTIFY worldIdChanged) - Q_PROPERTY(bool runOnSubframes READ runOnSubframes WRITE setRunOnSubframes NOTIFY runOnSubframesChanged) +namespace QtWebEngineCore { +class UserResourceControllerHost; +class WebContentsAdapter; +} // namespace +QT_BEGIN_NAMESPACE +class QQuickWebEngineScriptPrivate { public: - enum InjectionPoint { - Deferred, - DocumentReady, - DocumentCreation - }; - Q_ENUM(InjectionPoint) - - enum ScriptWorldId { - MainWorld = 0, - ApplicationWorld, - UserWorld - }; - Q_ENUM(ScriptWorldId) - - QQuickWebEngineScript(); - ~QQuickWebEngineScript(); - Q_INVOKABLE QString toString() const; - - QString name() const; - QUrl sourceUrl() const; - QString sourceCode() const; - InjectionPoint injectionPoint() const; - ScriptWorldId worldId() const; - bool runOnSubframes() const; + Q_DECLARE_PUBLIC(QQuickWebEngineScript) + QQuickWebEngineScriptPrivate(); + void aboutToUpdateUnderlyingScript(); + void bind(QtWebEngineCore::UserResourceControllerHost *, QtWebEngineCore::WebContentsAdapter * = 0); -public Q_SLOTS: - void setName(QString arg); - void setSourceUrl(QUrl arg); - void setSourceCode(QString arg); - void setInjectionPoint(InjectionPoint arg); - void setWorldId(ScriptWorldId arg); - void setRunOnSubframes(bool arg); - -Q_SIGNALS: - void nameChanged(QString arg); - void sourceUrlChanged(QUrl arg); - void sourceCodeChanged(QString arg); - void injectionPointChanged(InjectionPoint arg); - void worldIdChanged(ScriptWorldId arg); - void runOnSubframesChanged(bool arg); - -protected: - void timerEvent(QTimerEvent *e) override; + QtWebEngineCore::UserScript coreScript; + QBasicTimer m_basicTimer; + QtWebEngineCore::UserResourceControllerHost *m_controllerHost; + QtWebEngineCore::WebContentsAdapter *m_adapter; + QUrl m_sourceUrl; private: - friend class QQuickWebEngineViewPrivate; - Q_DECLARE_PRIVATE(QQuickWebEngineScript) - QScopedPointer<QQuickWebEngineScriptPrivate> d_ptr; + QQuickWebEngineScript *q_ptr; + }; + QT_END_NAMESPACE #endif // QQUICKWEBENGINESCRIPT_P_H diff --git a/src/webengine/api/qquickwebenginescript_p_p.h b/src/webengine/api/qquickwebenginescript_p_p.h deleted file mode 100644 index 4525505c6..000000000 --- a/src/webengine/api/qquickwebenginescript_p_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QQUICKWEBENGINESCRIPT_P_P_H -#define QQUICKWEBENGINESCRIPT_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qquickwebenginescript_p.h" - -#include <QtCore/QBasicTimer> -#include "user_script.h" -#include "web_contents_adapter.h" - -namespace QtWebEngineCore { -class UserResourceControllerHost; -class WebContentsAdapter; -} // namespace - -QT_BEGIN_NAMESPACE - -class QQuickWebEngineScriptPrivate { -public: - Q_DECLARE_PUBLIC(QQuickWebEngineScript) - QQuickWebEngineScriptPrivate(); - void aboutToUpdateUnderlyingScript(); - void bind(QtWebEngineCore::UserResourceControllerHost *, QtWebEngineCore::WebContentsAdapter * = 0); - - QtWebEngineCore::UserScript coreScript; - QBasicTimer m_basicTimer; - QtWebEngineCore::UserResourceControllerHost *m_controllerHost; - QtWebEngineCore::WebContentsAdapter *m_adapter; - QUrl m_sourceUrl; - -private: - QQuickWebEngineScript *q_ptr; - -}; - -QT_END_NAMESPACE - -#endif // QQUICKWEBENGINESCRIPT_P_P_H diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index fd89e3916..ff2541376 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -348,6 +348,21 @@ bool QQuickWebEngineSettings::allowRunningInsecureContent() const } /*! + \qmlproperty bool WebEngineSettings::allowGeolocationOnInsecureOrigins + \since QtWebEngine 1.5 + + Since Qt 5.7, only secure origins such as HTTPS have been able to request + Geolocation features. This provides an override to allow non secure + origins to access Geolocation again. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::allowGeolocationOnInsecureOrigins() const +{ + return d_ptr->testAttribute(WebEngineSettings::AllowGeolocationOnInsecureOrigins); +} + +/*! \qmlproperty string WebEngineSettings::defaultTextEncoding \since QtWebEngine 1.2 @@ -541,6 +556,14 @@ void QQuickWebEngineSettings::setAllowRunningInsecureContent(bool on) Q_EMIT allowRunningInsecureContentChanged(); } +void QQuickWebEngineSettings::setAllowGeolocationOnInsecureOrigins(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::AllowGeolocationOnInsecureOrigins); + d_ptr->setAttribute(WebEngineSettings::AllowGeolocationOnInsecureOrigins, on); + if (wasOn != on) + Q_EMIT allowGeolocationOnInsecureOriginsChanged(); +} + void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings) { d_ptr->setParentSettings(parentSettings->d_ptr.data()); diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index a53c7cdb3..10217c678 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -63,28 +63,29 @@ QT_BEGIN_NAMESPACE class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_OBJECT - Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages NOTIFY autoLoadImagesChanged) - Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled NOTIFY javascriptEnabledChanged) - Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows NOTIFY javascriptCanOpenWindowsChanged) - Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard NOTIFY javascriptCanAccessClipboardChanged) - Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain NOTIFY linksIncludedInFocusChainChanged) - Q_PROPERTY(bool localStorageEnabled READ localStorageEnabled WRITE setLocalStorageEnabled NOTIFY localStorageEnabledChanged) - Q_PROPERTY(bool localContentCanAccessRemoteUrls READ localContentCanAccessRemoteUrls WRITE setLocalContentCanAccessRemoteUrls NOTIFY localContentCanAccessRemoteUrlsChanged) - Q_PROPERTY(bool spatialNavigationEnabled READ spatialNavigationEnabled WRITE setSpatialNavigationEnabled NOTIFY spatialNavigationEnabledChanged) - Q_PROPERTY(bool localContentCanAccessFileUrls READ localContentCanAccessFileUrls WRITE setLocalContentCanAccessFileUrls NOTIFY localContentCanAccessFileUrlsChanged) - Q_PROPERTY(bool hyperlinkAuditingEnabled READ hyperlinkAuditingEnabled WRITE setHyperlinkAuditingEnabled NOTIFY hyperlinkAuditingEnabledChanged) - Q_PROPERTY(bool errorPageEnabled READ errorPageEnabled WRITE setErrorPageEnabled NOTIFY errorPageEnabledChanged) - Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled NOTIFY pluginsEnabledChanged) - Q_PROPERTY(bool fullScreenSupportEnabled READ fullScreenSupportEnabled WRITE setFullScreenSupportEnabled NOTIFY fullScreenSupportEnabledChanged REVISION 1) - Q_PROPERTY(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged) - Q_PROPERTY(bool screenCaptureEnabled READ screenCaptureEnabled WRITE setScreenCaptureEnabled NOTIFY screenCaptureEnabledChanged REVISION 2) - Q_PROPERTY(bool webGLEnabled READ webGLEnabled WRITE setWebGLEnabled NOTIFY webGLEnabledChanged REVISION 2) - Q_PROPERTY(bool accelerated2dCanvasEnabled READ accelerated2dCanvasEnabled WRITE setAccelerated2dCanvasEnabled NOTIFY accelerated2dCanvasEnabledChanged REVISION 2) - Q_PROPERTY(bool autoLoadIconsForPage READ autoLoadIconsForPage WRITE setAutoLoadIconsForPage NOTIFY autoLoadIconsForPageChanged REVISION 2) - Q_PROPERTY(bool touchIconsEnabled READ touchIconsEnabled WRITE setTouchIconsEnabled NOTIFY touchIconsEnabledChanged REVISION 2) - Q_PROPERTY(bool focusOnNavigationEnabled READ focusOnNavigationEnabled WRITE setFocusOnNavigationEnabled NOTIFY focusOnNavigationEnabledChanged REVISION 3) - Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION 3) - Q_PROPERTY(bool allowRunningInsecureContent READ allowRunningInsecureContent WRITE setAllowRunningInsecureContent NOTIFY allowRunningInsecureContentChanged REVISION 3) + Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages NOTIFY autoLoadImagesChanged FINAL) + Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled NOTIFY javascriptEnabledChanged FINAL) + Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows NOTIFY javascriptCanOpenWindowsChanged FINAL) + Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard NOTIFY javascriptCanAccessClipboardChanged FINAL) + Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain NOTIFY linksIncludedInFocusChainChanged FINAL) + Q_PROPERTY(bool localStorageEnabled READ localStorageEnabled WRITE setLocalStorageEnabled NOTIFY localStorageEnabledChanged FINAL) + Q_PROPERTY(bool localContentCanAccessRemoteUrls READ localContentCanAccessRemoteUrls WRITE setLocalContentCanAccessRemoteUrls NOTIFY localContentCanAccessRemoteUrlsChanged FINAL) + Q_PROPERTY(bool spatialNavigationEnabled READ spatialNavigationEnabled WRITE setSpatialNavigationEnabled NOTIFY spatialNavigationEnabledChanged FINAL) + Q_PROPERTY(bool localContentCanAccessFileUrls READ localContentCanAccessFileUrls WRITE setLocalContentCanAccessFileUrls NOTIFY localContentCanAccessFileUrlsChanged FINAL) + Q_PROPERTY(bool hyperlinkAuditingEnabled READ hyperlinkAuditingEnabled WRITE setHyperlinkAuditingEnabled NOTIFY hyperlinkAuditingEnabledChanged FINAL) + Q_PROPERTY(bool errorPageEnabled READ errorPageEnabled WRITE setErrorPageEnabled NOTIFY errorPageEnabledChanged FINAL) + Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled NOTIFY pluginsEnabledChanged FINAL) + Q_PROPERTY(bool fullScreenSupportEnabled READ fullScreenSupportEnabled WRITE setFullScreenSupportEnabled NOTIFY fullScreenSupportEnabledChanged REVISION 1 FINAL) + Q_PROPERTY(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged FINAL) + Q_PROPERTY(bool screenCaptureEnabled READ screenCaptureEnabled WRITE setScreenCaptureEnabled NOTIFY screenCaptureEnabledChanged REVISION 2 FINAL) + Q_PROPERTY(bool webGLEnabled READ webGLEnabled WRITE setWebGLEnabled NOTIFY webGLEnabledChanged REVISION 2 FINAL) + Q_PROPERTY(bool accelerated2dCanvasEnabled READ accelerated2dCanvasEnabled WRITE setAccelerated2dCanvasEnabled NOTIFY accelerated2dCanvasEnabledChanged REVISION 2 FINAL) + Q_PROPERTY(bool autoLoadIconsForPage READ autoLoadIconsForPage WRITE setAutoLoadIconsForPage NOTIFY autoLoadIconsForPageChanged REVISION 2 FINAL) + Q_PROPERTY(bool touchIconsEnabled READ touchIconsEnabled WRITE setTouchIconsEnabled NOTIFY touchIconsEnabledChanged REVISION 2 FINAL) + Q_PROPERTY(bool focusOnNavigationEnabled READ focusOnNavigationEnabled WRITE setFocusOnNavigationEnabled NOTIFY focusOnNavigationEnabledChanged REVISION 3 FINAL) + Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION 3 FINAL) + Q_PROPERTY(bool allowRunningInsecureContent READ allowRunningInsecureContent WRITE setAllowRunningInsecureContent NOTIFY allowRunningInsecureContentChanged REVISION 3 FINAL) + Q_PROPERTY(bool allowGeolocationOnInsecureOrigins READ allowGeolocationOnInsecureOrigins WRITE setAllowGeolocationOnInsecureOrigins NOTIFY allowGeolocationOnInsecureOriginsChanged REVISION 4 FINAL) public: ~QQuickWebEngineSettings(); @@ -111,6 +112,7 @@ public: bool focusOnNavigationEnabled() const; bool printElementBackgrounds() const; bool allowRunningInsecureContent() const; + bool allowGeolocationOnInsecureOrigins() const; void setAutoLoadImages(bool on); void setJavascriptEnabled(bool on); @@ -134,6 +136,7 @@ public: void setFocusOnNavigationEnabled(bool on); void setPrintElementBackgrounds(bool on); void setAllowRunningInsecureContent(bool on); + void setAllowGeolocationOnInsecureOrigins(bool on); signals: void autoLoadImagesChanged(); @@ -158,6 +161,7 @@ signals: Q_REVISION(3) void focusOnNavigationEnabledChanged(); Q_REVISION(3) void printElementBackgroundsChanged(); Q_REVISION(3) void allowRunningInsecureContentChanged(); + Q_REVISION(4) void allowGeolocationOnInsecureOriginsChanged(); private: explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0); diff --git a/src/webengine/api/qquickwebenginetestsupport_p.h b/src/webengine/api/qquickwebenginetestsupport_p.h index 79d51e7a3..cca8d1df4 100644 --- a/src/webengine/api/qquickwebenginetestsupport_p.h +++ b/src/webengine/api/qquickwebenginetestsupport_p.h @@ -75,14 +75,13 @@ Q_SIGNALS: class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTestSupport : public QObject { Q_OBJECT - Q_PROPERTY(QQuickWebEngineErrorPage *errorPage READ errorPage) + Q_PROPERTY(QQuickWebEngineErrorPage *errorPage READ errorPage CONSTANT FINAL) public: QQuickWebEngineTestSupport(); QQuickWebEngineErrorPage *errorPage() const; Q_SIGNALS: - void validationMessageShown(const QString &mainText, const QString &subText); void windowCloseRejected(); void loadVisuallyCommitted(); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index c1f1c9d0b..60fb5d0a5 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -55,7 +55,7 @@ #include "qquickwebenginenewviewrequest_p.h" #include "qquickwebengineprofile_p.h" #include "qquickwebenginesettings_p.h" -#include "qquickwebenginescript_p_p.h" +#include "qquickwebenginescript_p.h" #ifdef ENABLE_QML_TESTSUPPORT_API #include "qquickwebenginetestsupport_p.h" @@ -595,6 +595,8 @@ void QQuickWebEngineViewPrivate::adoptNewWindow(QSharedPointer<WebContentsAdapte // to start loading it and possibly return it to its parent page window.open(). request.m_adapter = newWebContents; request.m_isUserInitiated = userGesture; + if (newWebContents) + request.m_requestedUrl = newWebContents->requestedUrl(); switch (disposition) { case WebContentsAdapterClient::NewForegroundTabDisposition: @@ -1103,12 +1105,14 @@ void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, const QByteArra callback.call(args); } +void QQuickWebEngineViewPrivate::didPrintPageToPdf(const QString &filePath, bool success) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->pdfPrintingFinished(filePath, success); +} + void QQuickWebEngineViewPrivate::showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText) { -#ifdef ENABLE_QML_TESTSUPPORT_API - if (m_testSupport) - Q_EMIT m_testSupport->validationMessageShown(mainText, subText); -#endif Q_Q(QQuickWebEngineView); QQuickWebEngineFormValidationMessageRequest *request; request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::Show, @@ -1320,7 +1324,7 @@ void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { -#if defined (ENABLE_PDF) +#if defined(ENABLE_PDF) Q_D(QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 4f9e483bc..92eb5d7de 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -52,7 +52,7 @@ // #include <private/qtwebengineglobal_p.h> -#include "qquickwebenginescript_p.h" +#include "qquickwebenginescript.h" #include <QQuickItem> #include <QtGui/qcolor.h> @@ -81,8 +81,8 @@ class QQuickWebEngineTestSupport; class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFullScreenRequest { Q_GADGET - Q_PROPERTY(QUrl origin READ origin) - Q_PROPERTY(bool toggleOn READ toggleOn) + Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL) + Q_PROPERTY(bool toggleOn READ toggleOn CONSTANT FINAL) public: QQuickWebEngineFullScreenRequest(); QQuickWebEngineFullScreenRequest(QQuickWebEngineViewPrivate *viewPrivate, const QUrl &origin, bool toggleOn); @@ -98,31 +98,31 @@ private: const bool m_toggleOn; }; -#define LATEST_WEBENGINEVIEW_REVISION 4 +#define LATEST_WEBENGINEVIEW_REVISION 5 class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_OBJECT - Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) - Q_PROPERTY(QUrl icon READ icon NOTIFY iconChanged) - Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged) - Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged) - Q_PROPERTY(QString title READ title NOTIFY titleChanged) - Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY urlChanged) - Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY urlChanged) - Q_PROPERTY(bool isFullScreen READ isFullScreen NOTIFY isFullScreenChanged REVISION 1) - Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged REVISION 1) + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged FINAL) + Q_PROPERTY(QUrl icon READ icon NOTIFY iconChanged FINAL) + Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged FINAL) + Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged FINAL) + Q_PROPERTY(QString title READ title NOTIFY titleChanged FINAL) + Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY urlChanged FINAL) + Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY urlChanged FINAL) + Q_PROPERTY(bool isFullScreen READ isFullScreen NOTIFY isFullScreenChanged REVISION 1 FINAL) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged REVISION 1 FINAL) Q_PROPERTY(QQuickWebEngineProfile *profile READ profile WRITE setProfile NOTIFY profileChanged FINAL REVISION 1) - Q_PROPERTY(QQuickWebEngineSettings *settings READ settings REVISION 1) + Q_PROPERTY(QQuickWebEngineSettings *settings READ settings REVISION 1 CONSTANT FINAL) Q_PROPERTY(QQuickWebEngineHistory *navigationHistory READ navigationHistory CONSTANT FINAL REVISION 1) - Q_PROPERTY(QQmlWebChannel *webChannel READ webChannel WRITE setWebChannel NOTIFY webChannelChanged REVISION 1) + Q_PROPERTY(QQmlWebChannel *webChannel READ webChannel WRITE setWebChannel NOTIFY webChannelChanged REVISION 1 FINAL) Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 1) - Q_PROPERTY(bool activeFocusOnPress READ activeFocusOnPress WRITE setActiveFocusOnPress NOTIFY activeFocusOnPressChanged REVISION 2) - Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged REVISION 2) + Q_PROPERTY(bool activeFocusOnPress READ activeFocusOnPress WRITE setActiveFocusOnPress NOTIFY activeFocusOnPressChanged REVISION 2 FINAL) + Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged REVISION 2 FINAL) Q_PROPERTY(QSizeF contentsSize READ contentsSize NOTIFY contentsSizeChanged FINAL REVISION 3) Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged FINAL REVISION 3) Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged FINAL REVISION 3) Q_PROPERTY(bool recentlyAudible READ recentlyAudible NOTIFY recentlyAudibleChanged FINAL REVISION 3) - Q_PROPERTY(uint webChannelWorld READ webChannelWorld WRITE setWebChannelWorld NOTIFY webChannelWorldChanged REVISION 3) + Q_PROPERTY(uint webChannelWorld READ webChannelWorld WRITE setWebChannelWorld NOTIFY webChannelWorldChanged REVISION 3 FINAL) #ifdef ENABLE_QML_TESTSUPPORT_API Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport NOTIFY testSupportChanged FINAL) @@ -512,6 +512,7 @@ Q_SIGNALS: Q_REVISION(4) void colorDialogRequested(QQuickWebEngineColorDialogRequest *request); Q_REVISION(4) void fileDialogRequested(QQuickWebEngineFileDialogRequest *request); Q_REVISION(4) void formValidationMessageRequested(QQuickWebEngineFormValidationMessageRequest *request); + Q_REVISION(5) void pdfPrintingFinished(const QString &filePath, bool success); #ifdef ENABLE_QML_TESTSUPPORT_API void testSupportChanged(); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index d692140ef..2ecd70d78 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -123,6 +123,7 @@ 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; + virtual void didPrintPageToPdf(const QString &filePath, bool success) Q_DECL_OVERRIDE; 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/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index 364fa6c8a..160cb4415 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -1101,14 +1101,34 @@ */ /*! + \qmlsignal WebEngineView::pdfPrintingFinished(string filePath, bool success) + \since QtWebEngine 1.5 + + This signal is emitted when printing the web page into a PDF file has + finished. + \a filePath will contain the path the file was requested to be created + at, and \a success will be \c true if the file was successfully created and + \c false otherwise. + + \sa printToPdf() +*/ + +/*! \qmlmethod void WebEngineView::printToPdf(const string filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) \since QtWebEngine 1.3 - Prints the WebEngineView's current content to a PDF document and stores it under \a filePath. The document's size will be determined - by the value of \a pageSizeId and its orientation will be determined using \a orientation. + Prints the WebEngineView's current content to a PDF document and stores it + under \a filePath. The document's size will be determined by the value of + \a pageSizeId and its orientation will be determined using \a orientation. + + This method issues an asynchronous request for printing the web page into a + PDF and returns immediately. To be informed about the result of the + request, connect to the signal pdfPrintingFinished(). If you leave out \a pageSizeID, it defaults to \c A4. If you leave out \a orientation, it defaults to \c Portrait. + + \sa pdfPrintingFinished() */ /*! diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index 0fd2087d4..f973336f0 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -98,11 +98,15 @@ public: tr("Cannot create a separate instance of WebEngineDownloadItem")); qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 3>(uri, 1, 4, "WebEngineDownloadItem", tr("Cannot create a separate instance of WebEngineDownloadItem")); + qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 4>(uri, 1, 5, "WebEngineDownloadItem", + tr("Cannot create a separate instance of WebEngineDownloadItem")); qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", msgUncreatableType("WebEngineNewViewRequest")); + qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest, 1>(uri, 1, 2, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest")); qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterUncreatableType<QQuickWebEngineSettings, 1>(uri, 1, 2, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterUncreatableType<QQuickWebEngineSettings, 3>(uri, 1, 4, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); + qmlRegisterUncreatableType<QQuickWebEngineSettings, 4>(uri, 1, 5, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider); qmlRegisterUncreatableType<QQuickWebEngineHistory>(uri, 1, 1, "NavigationHistory", tr("Cannot create a separate instance of NavigationHistory")); diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 2bbf82810..27239225b 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -45,6 +45,7 @@ HEADERS = \ api/qquickwebenginenewviewrequest_p.h \ api/qquickwebengineprofile.h \ api/qquickwebengineprofile_p.h \ + api/qquickwebenginescript.h \ api/qquickwebenginescript_p.h \ api/qquickwebenginesettings_p.h \ api/qquickwebenginesingleton_p.h \ @@ -65,7 +66,7 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } -contains(WEBENGINE_CONFIG, enable_pdf) { +use?(pdf) { DEFINES += ENABLE_PDF } diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index 0bf02a7fc..1950221c7 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -46,6 +46,34 @@ QT_BEGIN_NAMESPACE using QtWebEngineCore::BrowserContextAdapterClient; +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NoReason, QWebEngineDownloadItem::NoReason) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileFailed, QWebEngineDownloadItem::FileFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileAccessDenied, QWebEngineDownloadItem::FileAccessDenied) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileNoSpace, QWebEngineDownloadItem::FileNoSpace) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileNameTooLong, QWebEngineDownloadItem::FileNameTooLong) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTooLarge, QWebEngineDownloadItem::FileTooLarge) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileVirusInfected, QWebEngineDownloadItem::FileVirusInfected) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTransientError, QWebEngineDownloadItem::FileTransientError) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileBlocked, QWebEngineDownloadItem::FileBlocked) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileSecurityCheckFailed, QWebEngineDownloadItem::FileSecurityCheckFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileTooShort, QWebEngineDownloadItem::FileTooShort) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::FileHashMismatch, QWebEngineDownloadItem::FileHashMismatch) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkFailed, QWebEngineDownloadItem::NetworkFailed) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkTimeout, QWebEngineDownloadItem::NetworkTimeout) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkDisconnected, QWebEngineDownloadItem::NetworkDisconnected) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkServerDown, QWebEngineDownloadItem::NetworkServerDown) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::NetworkInvalidRequest, QWebEngineDownloadItem::NetworkInvalidRequest) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerFailed, QWebEngineDownloadItem::ServerFailed) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerNoRange, QWebEngineDownloadItem::ServerNoRange) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerBadContent, QWebEngineDownloadItem::ServerBadContent) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerUnauthorized, QWebEngineDownloadItem::ServerUnauthorized) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerCertProblem, QWebEngineDownloadItem::ServerCertProblem) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerForbidden, QWebEngineDownloadItem::ServerForbidden) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::ServerUnreachable, QWebEngineDownloadItem::ServerUnreachable) +ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::UserCanceled, QWebEngineDownloadItem::UserCanceled) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::UserShutdown, QWebEngineDownloadItem::UserShutdown) +//ASSERT_ENUMS_MATCH(BrowserContextAdapterClient::Crash, QWebEngineDownloadItem::Crash) + static inline QWebEngineDownloadItem::DownloadState toDownloadState(int state) { switch (state) { @@ -63,6 +91,11 @@ static inline QWebEngineDownloadItem::DownloadState toDownloadState(int state) } } +static inline QWebEngineDownloadItem::DownloadInterruptReason toDownloadInterruptReason(int reason) +{ + return static_cast<QWebEngineDownloadItem::DownloadInterruptReason>(reason); +} + /*! \class QWebEngineDownloadItem \brief The QWebEngineDownloadItem class provides information about a download. @@ -81,6 +114,7 @@ QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePr , downloadState(QWebEngineDownloadItem::DownloadCancelled) , savePageFormat(QWebEngineDownloadItem::MimeHtmlSaveFormat) , type(QWebEngineDownloadItem::Attachment) + , interruptReason(QWebEngineDownloadItem::NoReason) , downloadUrl(url) , totalBytes(-1) , receivedBytes(0) @@ -97,6 +131,11 @@ void QWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClient::Do Q_ASSERT(downloadState != QWebEngineDownloadItem::DownloadRequested); + if (toDownloadInterruptReason(info.downloadInterruptReason) != interruptReason) { + interruptReason = toDownloadInterruptReason(info.downloadInterruptReason); + Q_EMIT q->interruptReasonChanged(); + } + if (toDownloadState(info.state) != downloadState) { downloadState = toDownloadState(info.state); Q_EMIT q->stateChanged(downloadState); @@ -192,6 +231,15 @@ quint32 QWebEngineDownloadItem::id() const */ /*! + \fn QWebEngineDownloadItem::interruptReasonChanged() + \since 5.9 + + This signal is emitted whenever the reason of the download's interruption changes. + + \sa interruptReason(), QWebEngineDownloadItem::DownloadInterruptReason +*/ + +/*! \enum QWebEngineDownloadItem::DownloadState This enum describes the state of the download: @@ -238,6 +286,45 @@ quint32 QWebEngineDownloadItem::id() const */ /*! + \enum QWebEngineDownloadItem::DownloadInterruptReason + \since 5.9 + + Describes the reason why a download was interrupted: + + \value NoReason Unknown reason or not interrupted. + \value FileFailed General file operation failure. + \value FileAccessDenied The file cannot be written locally, due to access restrictions. + \value FileNoSpace Insufficient space on the target drive. + \value FileNameTooLong The directory or file name is too long. + \value FileTooLarge The file size exceeds the file system limitation. + \value FileVirusInfected The file is infected with a virus. + \value FileTransientError Temporary problem (for example the file is in use, + out of memory, or too many files are opened at once). + \value FileBlocked The file was blocked due to local policy. + \value FileSecurityCheckFailed An attempt to check the safety of the download + failed due to unexpected reasons. + \value FileTooShort An attempt was made to seek past the end of a file when + opening a file (as part of resuming a previously interrupted download). + \value FileHashMismatch The partial file did not match the expected hash. + + \value NetworkFailed General network failure. + \value NetworkTimeout The network operation has timed out. + \value NetworkDisconnected The network connection has been terminated. + \value NetworkServerDown The server has gone down. + \value NetworkInvalidRequest The network request was invalid (for example, the + original or redirected URL is invalid, has an unsupported scheme, or is disallowed by policy). + + \value ServerFailed General server failure. + \value ServerBadContent The server does not have the requested data. + \value ServerUnauthorized The server did not authorize access to the resource. + \value ServerCertProblem A problem with the server certificate occurred. + \value ServerForbidden Access forbidden by the server. + \value ServerUnreachable Unexpected server response (might indicate that + the responding server may not be the intended server). + \value UserCanceled The user canceled the download. +*/ + +/*! Returns the download item's current state. \sa DownloadState @@ -374,6 +461,32 @@ QWebEngineDownloadItem::DownloadType QWebEngineDownloadItem::type() const return d->type; } +/*! + Returns the reason why the download was interrupted. + \since 5.9 + + \sa interruptReasonString() +*/ + +QWebEngineDownloadItem::DownloadInterruptReason QWebEngineDownloadItem::interruptReason() const +{ + Q_D(const QWebEngineDownloadItem); + return d->interruptReason; +} + +/*! + Returns a human-readable description of the reason for interrupting the download. + \since 5.9 + + \sa interruptReason() +*/ + +QString QWebEngineDownloadItem::interruptReasonString() const +{ + return BrowserContextAdapterClient::downloadInterruptReasonToString( + static_cast<BrowserContextAdapterClient::DownloadInterruptReason>(interruptReason())); +} + QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h index 4b58748ad..846194f40 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem.h @@ -72,6 +72,37 @@ public: }; Q_ENUM(SavePageFormat) + enum DownloadInterruptReason { + NoReason = 0, + FileFailed = 1, + FileAccessDenied = 2, + FileNoSpace = 3, + FileNameTooLong = 5, + FileTooLarge = 6, + FileVirusInfected = 7, + FileTransientError = 10, + FileBlocked = 11, + FileSecurityCheckFailed = 12, + FileTooShort = 13, + FileHashMismatch = 14, + NetworkFailed = 20, + NetworkTimeout = 21, + NetworkDisconnected = 22, + NetworkServerDown = 23, + NetworkInvalidRequest = 24, + ServerFailed = 30, + //ServerNoRange = 31, + ServerBadContent = 33, + ServerUnauthorized = 34, + ServerCertProblem = 35, + ServerForbidden = 36, + ServerUnreachable = 37, + UserCanceled = 40, + //UserShutdown = 41, + //Crash = 50 + }; + Q_ENUM(DownloadInterruptReason) + enum DownloadType { Attachment = 0, DownloadAttribute, @@ -92,6 +123,8 @@ public: SavePageFormat savePageFormat() const; void setSavePageFormat(SavePageFormat format); DownloadType type() const; + DownloadInterruptReason interruptReason() const; + QString interruptReasonString() const; public Q_SLOTS: void accept(); @@ -101,6 +134,7 @@ Q_SIGNALS: void finished(); void stateChanged(QWebEngineDownloadItem::DownloadState state); void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void interruptReasonChanged(); private: Q_DISABLE_COPY(QWebEngineDownloadItem) diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h index 9ddb45444..038332da3 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h @@ -73,6 +73,7 @@ public: QWebEngineDownloadItem::DownloadState downloadState; QWebEngineDownloadItem::SavePageFormat savePageFormat; QWebEngineDownloadItem::DownloadType type; + QWebEngineDownloadItem::DownloadInterruptReason interruptReason; QString downloadPath; const QUrl downloadUrl; QString mimeType; diff --git a/src/webenginewidgets/api/qwebenginefullscreenrequest.h b/src/webenginewidgets/api/qwebenginefullscreenrequest.h index e5f2b7b19..08505a410 100644 --- a/src/webenginewidgets/api/qwebenginefullscreenrequest.h +++ b/src/webenginewidgets/api/qwebenginefullscreenrequest.h @@ -49,8 +49,8 @@ class QWebEnginePage; class QWEBENGINEWIDGETS_EXPORT QWebEngineFullScreenRequest { Q_GADGET - Q_PROPERTY(bool toggleOn READ toggleOn) - Q_PROPERTY(QUrl origin READ origin) + Q_PROPERTY(bool toggleOn READ toggleOn CONSTANT) + Q_PROPERTY(QUrl origin READ origin CONSTANT) public: Q_INVOKABLE void reject(); Q_INVOKABLE void accept(); diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index eeb5524a0..8908af3c4 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -80,9 +80,11 @@ #include <QMenu> #include <QMessageBox> #include <QMimeData> +#if defined(QT_PRINTSUPPORT_LIB) #ifndef QT_NO_PRINTER #include <QPrinter> -#endif +#endif //QT_NO_PRINTER +#endif //QT_PRINTSUPPORT_LIB #include <QStandardPaths> #include <QStyle> #include <QTimer> @@ -96,8 +98,7 @@ using namespace QtWebEngineCore; static const int MaxTooltipLength = 1024; -#ifndef QT_NO_PRINTER -#if defined(ENABLE_PDF) +#if defined(ENABLE_PRINTING) && defined(ENABLE_PDF) static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) { QRect printerPageRect = printer.pageRect(); @@ -174,8 +175,7 @@ static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) return true; } -#endif // defined(ENABLE_PDF) -#endif // QT_NO_PRINTER +#endif // defined(ENABLE_PRINTING) && defined(ENABLE_PDF) static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { @@ -227,7 +227,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , fullscreenMode(false) , webChannel(nullptr) , webChannelWorldId(QWebEngineScript::MainWorld) -#ifndef QT_NO_PRINTER +#if defined(ENABLE_PRINTING) , currentPrinter(nullptr) #endif { @@ -359,6 +359,12 @@ void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isE updateNavigationActions(); } +void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool success) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->pdfPrintingFinished(filePath, success); +} + void QWebEnginePagePrivate::focusContainer() { if (view) @@ -478,7 +484,7 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) { #if defined(ENABLE_PDF) -#ifndef QT_NO_PRINTER +#if defined(ENABLE_PRINTING) // If no currentPrinter is set that means that were printing to PDF only. if (!currentPrinter) { m_callbacks.invoke(requestId, result); @@ -491,7 +497,7 @@ void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &re currentPrinter = nullptr; #else // If print support is disabled, only PDF printing is available. m_callbacks.invoke(requestId, result); -#endif // ifndef QT_NO_PRINTER +#endif // defined(ENABLE_PRINTING) #else // defined(ENABLE_PDF) // we should never enter this branch, but just for safe-keeping... Q_UNUSED(result); @@ -729,6 +735,19 @@ QWebEnginePage::QWebEnginePage(QObject* parent) */ /*! + \fn void QWebEnginePage::pdfPrintingFinished(const QString &filePath, bool success) + \since 5.9 + + This signal is emitted when printing the web page into a PDF file has + finished. + \a filePath will contain the path the file was requested to be created + at, and \a success will be \c true if the file was successfully created and + \c false otherwise. + + \sa printToPdf() +*/ + +/*! \property QWebEnginePage::scrollPosition \since 5.7 @@ -1688,6 +1707,18 @@ void QWebEnginePage::load(const QUrl& url) d->adapter->load(url); } +/*! + \since 5.9 + Issues the specified \a request and loads the response. + + \sa load(), setUrl(), url(), urlChanged(), QUrl::fromUserInput() +*/ +void QWebEnginePage::load(const QWebEngineHttpRequest& request) +{ + Q_D(QWebEnginePage); + d->adapter->load(request); +} + void QWebEnginePage::toHtml(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); @@ -1940,17 +1971,25 @@ QSizeF QWebEnginePage::contentsSize() const } /*! - Renders the current content of the page into a PDF document and saves it in the location specified in \a filePath. - The page size and orientation of the produced PDF document are taken from the values specified in \a pageLayout. + Renders the current content of the page into a PDF document and saves it + in the location specified in \a filePath. + The page size and orientation of the produced PDF document are taken from + the values specified in \a pageLayout. + + This method issues an asynchronous request for printing the web page into + a PDF and returns immediately. + To be informed about the result of the request, connect to the signal + pdfPrintingFinished(). If a file already exists at the provided file path, it will be overwritten. \since 5.7 + \sa pdfPrintingFinished() */ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &pageLayout) { #if defined(ENABLE_PDF) Q_D(const QWebEnginePage); -#ifndef QT_NO_PRINTER +#if defined(ENABLE_PRINTING) 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())); @@ -1959,7 +1998,7 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page #endif return; } -#endif +#endif // ENABLE_PRINTING d->adapter->printToPDF(pageLayout, filePath); #else Q_UNUSED(filePath); @@ -1983,7 +2022,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res { Q_D(QWebEnginePage); #if defined(ENABLE_PDF) -#ifndef QT_NO_PRINTER +#if defined(ENABLE_PRINTING) 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())); @@ -1993,7 +2032,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res d->m_callbacks.invokeEmpty(resultCallback); return; } -#endif // ifndef QT_NO_PRINTER +#endif // ENABLE_PRINTING quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.registerCallback(requestId, resultCallback); #else // if defined(ENABLE_PDF) @@ -2002,6 +2041,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res #endif // if defined(ENABLE_PDF) } +#if defined(QT_PRINTSUPPORT_LIB) #ifndef QT_NO_PRINTER /*! \fn void QWebEnginePage::print(QPrinter *printer, FunctorOrLambda resultCallback) @@ -2020,6 +2060,7 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re { Q_D(QWebEnginePage); #if defined(ENABLE_PDF) +#if defined(ENABLE_PRINTING) 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())); @@ -2030,6 +2071,7 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re return; } d->currentPrinter = printer; +#endif // ENABLE_PRINTING quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(), printer->colorMode() == QPrinter::Color); d->m_callbacks.registerCallback(requestId, resultCallback); #else // if defined(ENABLE_PDF) @@ -2037,7 +2079,8 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re d->m_callbacks.invokeDirectly(resultCallback, false); #endif // if defined(ENABLE_PDF) } -#endif // QT_NO_PRINTER +#endif // if defined(QT_NO_PRINTER) +#endif // if defined(QT_PRINTSUPPORT_LIB) /*! \since 5.7 diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index e85f9b30e..6140cf445 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -44,6 +44,7 @@ #include <QtWebEngineWidgets/qwebenginecertificateerror.h> #include <QtWebEngineWidgets/qwebenginedownloaditem.h> #include <QtWebEngineCore/qwebenginecallback.h> +#include <QtWebEngineCore/qwebenginehttprequest.h> #include <QtCore/qobject.h> #include <QtCore/qurl.h> @@ -54,9 +55,12 @@ QT_BEGIN_NAMESPACE class QMenu; +#if defined(QT_PRINTSUPPORT_LIB) #ifndef QT_NO_PRINTER class QPrinter; -#endif +#endif // QT_NO_PRINTER +#endif // QT_PRINTSUPPORT_LIB + class QWebChannel; class QWebEngineContextMenuData; class QWebEngineFullScreenRequest; @@ -224,8 +228,8 @@ public: void setFeaturePermission(const QUrl &securityOrigin, Feature feature, PermissionPolicy policy); - // Ex-QWebFrame methods void load(const QUrl &url); + void load(const QWebEngineHttpRequest &request); void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); @@ -282,6 +286,7 @@ public: void printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF())); #endif +#if defined(QT_PRINTSUPPORT_LIB) #ifndef QT_NO_PRINTER #ifdef Q_QDOC void print(QPrinter *printer, FunctorOrLambda resultCallback); @@ -289,6 +294,7 @@ public: void print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback); #endif // QDOC #endif // QT_NO_PRINTER +#endif // QT_PRINTSUPPORT_LIB const QWebEngineContextMenuData &contextMenuData() const; @@ -322,6 +328,8 @@ Q_SIGNALS: void audioMutedChanged(bool muted); void recentlyAudibleChanged(bool recentlyAudible); + void pdfPrintingFinished(const QString &filePath, bool success); + protected: virtual QWebEnginePage *createWindow(WebWindowType type); virtual QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 0ad077a0e..c7b805c45 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -119,6 +119,7 @@ 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; + virtual void didPrintPageToPdf(const QString &filePath, bool success) Q_DECL_OVERRIDE; 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; @@ -178,9 +179,9 @@ public: mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; -#ifndef QT_NO_PRINTER +#if defined(ENABLE_PRINTING) QPrinter *currentPrinter; -#endif // QT_NO_PRINTER +#endif }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index 50002e3e6..08d24376a 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -95,6 +95,8 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::PrintElementBackgrounds; case QWebEngineSettings::AllowRunningInsecureContent: return WebEngineSettings::AllowRunningInsecureContent; + case QWebEngineSettings::AllowGeolocationOnInsecureOrigins: + return WebEngineSettings::AllowGeolocationOnInsecureOrigins; default: return WebEngineSettings::UnsupportedInCoreSettings; diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index e3fb83ff5..73995a457 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -88,7 +88,8 @@ public: TouchIconsEnabled, FocusOnNavigationEnabled, PrintElementBackgrounds, - AllowRunningInsecureContent + AllowRunningInsecureContent, + AllowGeolocationOnInsecureOrigins }; enum FontSize { diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 63cf30d67..56948bb18 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -175,6 +175,17 @@ void QWebEngineView::load(const QUrl& url) page()->load(url); } +/*! + \since 5.9 + Issues the specified \a request and loads the response. + + \sa load(), setUrl(), url(), urlChanged(), QUrl::fromUserInput() +*/ +void QWebEngineView::load(const QWebEngineHttpRequest &request) +{ + page()->load(request); +} + void QWebEngineView::setHtml(const QString& html, const QUrl& baseUrl) { page()->setHtml(html, baseUrl); diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h index cb66bb75f..487cc2316 100644 --- a/src/webenginewidgets/api/qwebengineview.h +++ b/src/webenginewidgets/api/qwebengineview.h @@ -46,6 +46,7 @@ #include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h> #include <QtWebEngineWidgets/qwebenginepage.h> +#include <QtWebEngineCore/qwebenginehttprequest.h> QT_BEGIN_NAMESPACE class QContextMenuEvent; @@ -71,7 +72,8 @@ public: QWebEnginePage* page() const; void setPage(QWebEnginePage* page); - void load(const QUrl& url); + void load(const QUrl &url); + void load(const QWebEngineHttpRequest &request); void setHtml(const QString& html, const QUrl& baseUrl = QUrl()); void setContent(const QByteArray& data, const QString& mimeType = QString(), const QUrl& baseUrl = QUrl()); diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index 5d01f331e..efbeb1991 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -161,6 +161,12 @@ web-sockets from HTTP URLs. This provides an override to get the old insecure behavior. Disabled by default. (Added in Qt 5.8) + \value AllowGeolocationOnInsecureOrigins + Since Qt 5.7, only secure origins such as HTTPS have been able to request + Geolocation features. This provides an override to allow non secure + origins to access Geolocation again. + Disabled by default. (Added in Qt 5.9) + */ /*! diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 5b96459af..3b27ca146 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -117,7 +117,7 @@ \note The view remains the same until enough data has arrived to display the new URL. - \sa setUrl(), url(), urlChanged(), QUrl::fromUserInput() + \sa load(), setUrl(), url(), urlChanged(), QUrl::fromUserInput() */ /*! diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro index b60de6e1e..ad79c1ef9 100644 --- a/src/webenginewidgets/webenginewidgets.pro +++ b/src/webenginewidgets/webenginewidgets.pro @@ -52,11 +52,13 @@ contains(WEBENGINE_CONFIG, use_spellchecker) { DEFINES += ENABLE_SPELLCHECK } -contains(WEBENGINE_CONFIG, enable_pdf) { - DEFINES += ENABLE_PDF +use?(printing) { + DEFINES += ENABLE_PRINTING + QT += printsupport } -qtHaveModule(printsupport) { - QT += printsupport +use?(pdf) { + DEFINES += ENABLE_PDF } + load(qt_module) diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp index f762e9b5c..e45b4466c 100644 --- a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp +++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp @@ -32,6 +32,7 @@ #include <QScopedPointer> #include <QtQml/QQmlEngine> #include <QtTest/QtTest> +#include <QQuickWebEngineProfile> #include <private/qquickwebengineview_p.h> #define INSPECTOR_SERVER_PORT "23654" @@ -62,6 +63,7 @@ tst_InspectorServer::tst_InspectorServer() { qputenv("QTWEBENGINE_REMOTE_DEBUGGING", INSPECTOR_SERVER_PORT); QtWebEngine::initialize(); + QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); prepareWebViewComponent(); } diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index f9fd854cc..5cc0d18df 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -34,6 +34,7 @@ #include <QQmlListProperty> #include <QtTest/QtTest> #include <QtWebEngine/QQuickWebEngineProfile> +#include <QtWebEngine/QQuickWebEngineScript> #include <private/qquickwebengineview_p.h> #include <private/qquickwebenginecertificateerror_p.h> #include <private/qquickwebenginedialogrequests_p.h> @@ -42,7 +43,6 @@ #include <private/qquickwebengineloadrequest_p.h> #include <private/qquickwebenginenavigationrequest_p.h> #include <private/qquickwebenginenewviewrequest_p.h> -#include <private/qquickwebenginescript_p.h> #include <private/qquickwebenginesettings_p.h> #include <private/qquickwebenginesingleton_p.h> #include <private/qquickwebenginecontextmenurequest_p.h> diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST index dd8258ba4..5788ce25b 100644 --- a/tests/auto/quick/qmltests/BLACKLIST +++ b/tests/auto/quick/qmltests/BLACKLIST @@ -10,3 +10,11 @@ linux [DesktopWebEngineViewLinkHovered::test_linkHoveredDoesntEmitRepeated] linux +[WebEngineViewSingleFileUpload::test_acceptDirectory] +* + +[WebEngineViewSingleFileUpload::test_acceptMultipleFilesSelection] +* + +[WebEngineViewSingleFileUpload::test_acceptSingleFileSelection] +* diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml index aa1f77942..a7d890072 100644 --- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml +++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml @@ -53,7 +53,7 @@ WebEngineView { return _waitFor(function() { return windowCloseRequestedSignalEmitted; }); } function _waitFor(predicate) { - var timeout = 5000 + var timeout = 12000 var i = 0 while (i < timeout && !predicate()) { testResult.wait(50) diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml index 4e74af733..655789bb3 100644 --- a/tests/auto/quick/qmltests/data/tst_filePicker.qml +++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml @@ -41,6 +41,11 @@ TestWebEngineView { target: webEngineView signalName: "titleChanged" } + SignalSpy { + id: terminationSpy + target: webEngineView + signalName: "renderProcessTerminated" + } TestCase { name: "WebEngineViewSingleFileUpload" @@ -51,11 +56,16 @@ TestWebEngineView { FilePickerParams.selectFiles = false FilePickerParams.selectedFilesUrl = [] titleSpy.clear() + terminationSpy.clear() } - // FIXME: Almost every second url loading progress does get stuck at about 90 percent, so the loadFinished signal won't arrive. - // This cleanup function is a workaround for this problem. function cleanup() { + // Test that the render process doesn't crash, and make sure if it does it does so now. + wait(1000) + verify(terminationSpy.count == 0, "Render process didn't self terminate") + + // FIXME: Almost every second url loading progress does get stuck at about 90 percent, so the loadFinished signal won't arrive. + // This cleanup function is a workaround for this problem. webEngineView.url = Qt.resolvedUrl("about:blank") webEngineView.waitForLoadSucceeded() } diff --git a/tests/auto/quick/qmltests/data/tst_formValidation.qml b/tests/auto/quick/qmltests/data/tst_formValidation.qml index cae41821c..182a2eaa9 100644 --- a/tests/auto/quick/qmltests/data/tst_formValidation.qml +++ b/tests/auto/quick/qmltests/data/tst_formValidation.qml @@ -28,22 +28,17 @@ import QtQuick 2.0 import QtTest 1.0 -import QtWebEngine 1.2 -import QtWebEngine.testsupport 1.0 +import QtWebEngine 1.4 TestWebEngineView { id: webEngineView width: 400 height: 300 - testSupport: WebEngineTestSupport { - id: testSupportAPI - } - SignalSpy { - id: showSpy - target: testSupportAPI - signalName: "validationMessageShown" + id: formValidationMessageRequestSpy + target: webEngineView + signalName: "formValidationMessageRequested" } TestCase { @@ -51,63 +46,75 @@ TestWebEngineView { when: windowShown function init() { - webEngineView.url = Qt.resolvedUrl("about:blank") - verify(webEngineView.waitForLoadSucceeded()) - showSpy.clear() + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + formValidationMessageRequestSpy.clear(); } function test_urlForm() { - webEngineView.url = Qt.resolvedUrl("forms.html#url_empty") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[0][0], "Please fill out this field.") + webEngineView.url = Qt.resolvedUrl("forms.html#url_empty"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[0][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[0][0].text, "Please fill out this field."); - webEngineView.url = Qt.resolvedUrl("about:blank") - verify(webEngineView.waitForLoadSucceeded()) + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[1][0].type, FormValidationMessageRequest.Hide); - webEngineView.url = Qt.resolvedUrl("forms.html#url_invalid") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[1][0], "Please enter a URL.") + webEngineView.url = Qt.resolvedUrl("forms.html#url_invalid"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[2][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[2][0].text, "Please enter a URL."); } function test_emailForm() { - webEngineView.url = Qt.resolvedUrl("forms.html#email_empty") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[0][0], "Please fill out this field.") + webEngineView.url = Qt.resolvedUrl("forms.html#email_empty"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[0][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[0][0].text, "Please fill out this field."); - webEngineView.url = Qt.resolvedUrl("about:blank") - verify(webEngineView.waitForLoadSucceeded()) + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[1][0].type, FormValidationMessageRequest.Hide); - webEngineView.url = Qt.resolvedUrl("forms.html#email_invalid") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[1][0], "Please include an '@' in the email address. 'invalid' is missing an '@'.") + webEngineView.url = Qt.resolvedUrl("forms.html#email_invalid"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[2][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[2][0].text, "Please include an '@' in the email address. 'invalid' is missing an '@'."); } function test_textForm() { - webEngineView.url = Qt.resolvedUrl("forms.html#input_empty") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[0][0], "Please fill out this field.") + webEngineView.url = Qt.resolvedUrl("forms.html#input_empty"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[0][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[0][0].text, "Please fill out this field."); // Title should be shown for pattern mismatch only - compare(showSpy.signalArguments[0][1], "") + compare(formValidationMessageRequestSpy.signalArguments[0][0].subText, ""); - webEngineView.url = Qt.resolvedUrl("about:blank") - verify(webEngineView.waitForLoadSucceeded()) + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[1][0].type, FormValidationMessageRequest.Hide); - webEngineView.url = Qt.resolvedUrl("forms.html#lorem_ipsum") - verify(webEngineView.waitForLoadSucceeded()) - keyPress(Qt.Key_Enter) - showSpy.wait() - compare(showSpy.signalArguments[1][0], "Please match the requested format.") - compare(showSpy.signalArguments[1][1], "Should type 'Lorem ipsum'") + webEngineView.url = Qt.resolvedUrl("forms.html#lorem_ipsum"); + verify(webEngineView.waitForLoadSucceeded()); + keyPress(Qt.Key_Enter); + formValidationMessageRequestSpy.wait(); + compare(formValidationMessageRequestSpy.signalArguments[2][0].type, FormValidationMessageRequest.Show); + compare(formValidationMessageRequestSpy.signalArguments[2][0].text, "Please match the requested format."); + compare(formValidationMessageRequestSpy.signalArguments[2][0].subText, "Should type 'Lorem ipsum'"); } } } diff --git a/tests/auto/quick/qmltests/data/tst_loadFail.qml b/tests/auto/quick/qmltests/data/tst_loadFail.qml index 9ce70fc96..47f4a2862 100644 --- a/tests/auto/quick/qmltests/data/tst_loadFail.qml +++ b/tests/auto/quick/qmltests/data/tst_loadFail.qml @@ -139,7 +139,7 @@ TestWebEngineView { verify(loadRequest.isErrorPage) compare(webEngineView.url, unavailableUrl) - compare(webEngineView.title, unavailableUrl + " failed to load") + compare(webEngineView.title, unavailableUrl) } } } diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index 2a43e1577..2cb9f6b81 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -126,7 +126,7 @@ TestWebEngineView { // Test failed load var bogusSite = "http://www.somesitethatdoesnotexist.abc/"; webEngineView.url = bogusSite; - tryCompare(loadRequestArray, "length", 2); + tryCompare(loadRequestArray, "length", 2, 12000); loadRequest = loadRequestArray[0]; compare(loadRequest.status, WebEngineView.LoadStartedStatus); @@ -217,7 +217,7 @@ TestWebEngineView { } webEngineView.loadingChanged.connect(handleLoadFailed); webEngineView.url = bogusSite - tryCompare(loadRequestArray, "length", 4); + tryCompare(loadRequestArray, "length", 4, 12000); webEngineView.loadingChanged.disconnect(handleLoadFailed); loadRequest = loadRequestArray[0]; diff --git a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml index 906dc1658..69aa76b77 100644 --- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml +++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml @@ -57,24 +57,40 @@ Item { } function test_keyboardModifierMapping() { - webEngineView.loadHtml("<input type='text'/>") - webEngineView.waitForLoadSucceeded() - webEngineView.runJavaScript("document.body.firstChild.focus()") + webEngineView.url = Qt.resolvedUrl("keyboardEvents.html"); + verify(webEngineView.waitForLoadSucceeded()); - keyPress(Qt.Key_A) - keyRelease(Qt.Key_A) - keyPress(Qt.Key_Left) - keyRelease(Qt.Key_Left) - keyPress(Qt.Key_Left) - keyRelease(Qt.Key_Left) + webEngineView.runJavaScript("document.getElementById('first_div').focus()"); + webEngineView.verifyElementHasFocus("first_div"); - tryCompare(parentItem.pressEvents, "length", 1) - compare(parentItem.pressEvents[0], Qt.Key_Left) + keyPress(Qt.Key_Right); + keyRelease(Qt.Key_Right); + // Right arrow key is unhandled thus focus is not changed + tryCompare(parentItem.releaseEvents, "length", 1); + webEngineView.verifyElementHasFocus("first_div"); - tryCompare(parentItem.releaseEvents, "length", 3) - compare(parentItem.releaseEvents[0], Qt.Key_A) - compare(parentItem.releaseEvents[1], Qt.Key_Left) - compare(parentItem.releaseEvents[2], Qt.Key_Left) + keyPress(Qt.Key_Tab); + keyRelease(Qt.Key_Tab); + // Tab key is handled thus focus is changed + tryCompare(parentItem.releaseEvents, "length", 2); + webEngineView.verifyElementHasFocus("second_div"); + + keyPress(Qt.Key_Left); + keyRelease(Qt.Key_Left); + // Left arrow key is unhandled thus focus is not changed + tryCompare(parentItem.releaseEvents, "length", 3); + webEngineView.verifyElementHasFocus("second_div"); + + // The page will consume the Tab key to change focus between elements while the arrow + // keys won't be used. + compare(parentItem.pressEvents.length, 2); + compare(parentItem.pressEvents[0], Qt.Key_Right); + compare(parentItem.pressEvents[1], Qt.Key_Left); + + // Key releases will all come back unconsumed. + compare(parentItem.releaseEvents[0], Qt.Key_Right); + compare(parentItem.releaseEvents[1], Qt.Key_Tab); + compare(parentItem.releaseEvents[2], Qt.Key_Left); } } } diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml index 88fa6f6e3..e9a4eba99 100644 --- a/tests/auto/quick/qmltests/data/tst_userScripts.qml +++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml @@ -61,6 +61,12 @@ Item { } TestWebEngineView { + id: webEngineView2 + width: 400 + height: 300 + } + + TestWebEngineView { id: webEngineViewWithConditionalUserScripts width: 400 height: 300 @@ -82,6 +88,7 @@ Item { function init() { webEngineView.url = ""; webEngineView.userScripts = []; + webEngineView.profile.userScripts = []; } function test_oneScript() { @@ -173,5 +180,17 @@ Item { webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "Test page with huge link area"); } + + function test_profileWideScript() { + webEngineView.profile.userScripts = [ changeDocumentTitleScript ]; + + webEngineView.url = Qt.resolvedUrl("test1.html"); + webEngineView.waitForLoadSucceeded(); + compare(webEngineView.title, "New title"); + + webEngineView2.url = Qt.resolvedUrl("test1.html"); + webEngineView2.waitForLoadSucceeded(); + compare(webEngineView2.title, "New title"); + } } } diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml index 8076d99f8..22c3947d3 100644 --- a/tests/auto/quick/qmltests/data/tst_viewSource.qml +++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml @@ -103,8 +103,8 @@ TestWebEngineView { { tag: "view-source:about:blank", userInputUrl: "view-source:about:blank", loadSucceed: true, url: "view-source:about:blank", title: "view-source:about:blank" }, { tag: testLocalUrl, userInputUrl: testLocalUrl, loadSucceed: true, url: testLocalUrl, title: "test1.html" }, { tag: testLocalUrlWithoutScheme, userInputUrl: testLocalUrlWithoutScheme, loadSucceed: true, url: testLocalUrl, title: "test1.html" }, - { tag: "view-source:http://non.existent", userInputUrl: "view-source:http://non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "http://non.existent/ is not available" }, - { tag: "view-source:non.existent", userInputUrl: "view-source:non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "http://non.existent/ is not available" }, + { tag: "view-source:http://non.existent", userInputUrl: "view-source:http://non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "non.existent" }, + { tag: "view-source:non.existent", userInputUrl: "view-source:non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "non.existent" }, ]; } diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index 6b5c4d00b..5dc909709 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -28,10 +28,85 @@ #include <QtCore/QScopedPointer> #include <QtQuickTest/quicktest.h> +#include <QtWebEngine/QQuickWebEngineProfile> #include "qt_webengine_quicktest.h" +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#endif + +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) +static bool debuggerPresent() +{ + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) + return false; + char buffer[2048]; + ssize_t size = read(fd, buffer, sizeof(buffer) - 1); + if (size == -1) { + close(fd); + return false; + } + buffer[size] = 0; + const char tracerPidToken[] = "\nTracerPid:"; + char *tracerPid = strstr(buffer, tracerPidToken); + if (!tracerPid) { + close(fd); + return false; + } + tracerPid += sizeof(tracerPidToken); + long int pid = strtol(tracerPid, &tracerPid, 10); + close(fd); + return pid != 0; +} + +static void stackTrace() +{ + bool ok = false; + const int disableStackDump = qEnvironmentVariableIntValue("QTEST_DISABLE_STACK_DUMP", &ok); + if (ok && disableStackDump == 1) + return; + + if (debuggerPresent()) + return; + + fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); + char cmd[512]; + qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n" + "set prompt\n" + "set height 0\n" + "thread apply all where full\n" + "detach\n" + "quit\n" + "EOF\n", + (int)getpid()); + + if (system(cmd) == -1) + fprintf(stderr, "calling gdb failed\n"); + fprintf(stderr, "========= End of stack trace ==============\n"); +} + +static void sigSegvHandler(int signum) +{ + stackTrace(); + qFatal("Received signal %d", signum); +} +#endif + int main(int argc, char **argv) { +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) + struct sigaction sigAction; + + sigemptyset(&sigAction.sa_mask); + sigAction.sa_handler = &sigSegvHandler; + sigAction.sa_flags = 0; + + sigaction(SIGSEGV, &sigAction, 0); +#endif + // Inject the mock ui delegates module qputenv("QML2_IMPORT_PATH", QByteArray(TESTS_SOURCE_DIR "qmltests/mock-delegates")); QScopedPointer<Application> app; @@ -42,6 +117,11 @@ int main(int argc, char **argv) if (!QCoreApplication::instance()) app.reset(new Application(argc, argv)); QtWebEngine::initialize(); + QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); + + QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS + QTEST_SET_MAIN_SOURCE_PATH + int i = quick_test_main(argc, argv, "qmltests", QUICK_TEST_SOURCE_DIR); return i; } diff --git a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp index 9f2060898..3d44efa6a 100644 --- a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp +++ b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp @@ -44,6 +44,7 @@ #include <QtTest/QtTest> #include <QTimer> #include <private/qquickwebengineview_p.h> +#include <QQuickWebEngineProfile> class tst_QQuickWebEngineDefaultSurfaceFormat : public QObject { @@ -68,6 +69,7 @@ private: void tst_QQuickWebEngineDefaultSurfaceFormat::initEngineAndViewComponent() { m_engine = new QQmlEngine(this); + QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); m_component.reset(new QQmlComponent(m_engine, this)); m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n" "import QtWebEngine 1.2\n" diff --git a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro index 36e74a2a8..df9b3e1b7 100644 --- a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro +++ b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro @@ -4,3 +4,8 @@ exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc QT_PRIVATE += webengine-private gui-private HEADERS += ../shared/util.h + +use?(pdf) { + DEFINES += ENABLE_PDF +} + diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 2a43c9c1c..a6818c6ef 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -34,6 +34,7 @@ #include <QtGui/qpa/qwindowsysteminterface.h> #include <QtQml/QQmlEngine> #include <QtTest/QtTest> +#include <QtWebEngine/QQuickWebEngineProfile> #include <private/qquickwebengineview_p.h> #include <functional> @@ -77,6 +78,7 @@ private Q_SLOTS: void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled(); void changeLocale(); + void userScripts(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -91,6 +93,7 @@ private: tst_QQuickWebEngineView::tst_QQuickWebEngineView() { QtWebEngine::initialize(); + QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); m_testSourceDirPath = QString::fromLocal8Bit(TESTS_SOURCE_DIR); if (!m_testSourceDirPath.endsWith(QLatin1Char('/'))) @@ -499,15 +502,22 @@ void tst_QQuickWebEngineView::setZoomFactor() void tst_QQuickWebEngineView::printToPdf() { +#if !defined(ENABLE_PDF) + QSKIP("ENABLE_PDF"); +#else QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX"); QVERIFY(tempDir.isValid()); QQuickWebEngineView *view = webEngineView(); view->setUrl(urlFromTestPath("html/basic_page.html")); QVERIFY(waitForLoadSucceeded(view)); + QSignalSpy savePdfSpy(view, SIGNAL(pdfPrintingFinished(const QString&, bool))); QString path = tempDir.path() + "/print_success.pdf"; view->printToPdf(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait); - QTRY_VERIFY(QFile::exists(path)); + QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal"); + QList<QVariant> successArguments = savePdfSpy.takeFirst(); + QVERIFY2(successArguments.at(0).toString() == path, "File path for first saved PDF does not match arguments"); + QVERIFY2(successArguments.at(1).toBool() == true, "Printing to PDF file failed though it should succeed"); #if !defined(Q_OS_WIN) path = tempDir.path() + "/print_//fail.pdf"; @@ -515,7 +525,11 @@ void tst_QQuickWebEngineView::printToPdf() path = tempDir.path() + "/print_|fail.pdf"; #endif // #if !defined(Q_OS_WIN) view->printToPdf(path, QQuickWebEngineView::A4, QQuickWebEngineView::Portrait); - QTRY_VERIFY(!QFile::exists(path)); + QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal"); + QList<QVariant> failedArguments = savePdfSpy.takeFirst(); + QVERIFY2(failedArguments.at(0).toString() == path, "File path for second saved PDF does not match arguments"); + QVERIFY2(failedArguments.at(1).toBool() == false, "Printing to PDF file succeeded though it should fail"); +#endif // !defined(ENABLE_PDF) } void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled() @@ -671,37 +685,61 @@ void tst_QQuickWebEngineView::inputEventForwardingDisabledWhenActiveFocusOnPress void tst_QQuickWebEngineView::changeLocale() { + QStringList errorLines; QUrl url("http://non.existent/"); QLocale::setDefault(QLocale("de")); - QQuickWebEngineView *viewDE = newWebEngineView(); - QSignalSpy titleSpyHU(viewDE, SIGNAL(titleChanged())); - + QScopedPointer<QQuickWebEngineView> viewDE(newWebEngineView()); viewDE->setUrl(url); - QVERIFY(waitForLoadFailed(viewDE)); - QTRY_COMPARE(titleSpyHU.size(), 2); - QCOMPARE(viewDE->title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString())); + QVERIFY(waitForLoadFailed(viewDE.data())); - QLocale::setDefault(QLocale("en")); - QQuickWebEngineView *viewEN = newWebEngineView(); - QSignalSpy titleSpyEN(viewEN, SIGNAL(titleChanged())); + QTRY_VERIFY(!bodyInnerText(viewDE.data()).isEmpty()); + errorLines = bodyInnerText(viewDE.data()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("Diese Website ist nicht erreichbar")); + QLocale::setDefault(QLocale("en")); + QScopedPointer<QQuickWebEngineView> viewEN(newWebEngineView()); viewEN->setUrl(url); - QVERIFY(waitForLoadFailed(viewEN)); - QTRY_COMPARE(titleSpyEN.size(), 2); - QCOMPARE(viewEN->title(), QStringLiteral("%1 is not available").arg(url.toString())); + QVERIFY(waitForLoadFailed(viewEN.data())); + + QTRY_VERIFY(!bodyInnerText(viewEN.data()).isEmpty()); + errorLines = bodyInnerText(viewEN.data()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("This site can\u2019t be reached")); + // Reset error page viewDE->setUrl(QUrl("about:blank")); - QVERIFY(waitForLoadSucceeded(viewDE)); - titleSpyHU.clear(); + QVERIFY(waitForLoadSucceeded(viewDE.data())); + // Check whether an existing QWebEngineView keeps the language settings after changing the default locale viewDE->setUrl(url); - QVERIFY(waitForLoadFailed(viewDE)); - QTRY_COMPARE(titleSpyHU.size(), 2); - QCOMPARE(viewDE->title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString())); + QVERIFY(waitForLoadFailed(viewDE.data())); + + QTRY_VERIFY(!bodyInnerText(viewDE.data()).isEmpty()); + errorLines = bodyInnerText(viewDE.data()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("Diese Website ist nicht erreichbar")); +} + +void tst_QQuickWebEngineView::userScripts() +{ + QScopedPointer<QQuickWebEngineView> webEngineView1(newWebEngineView()); + webEngineView1->setParentItem(m_window->contentItem()); + QScopedPointer<QQuickWebEngineView> webEngineView2(newWebEngineView()); + webEngineView2->setParentItem(m_window->contentItem()); + + QQmlListReference list(webEngineView1->profile(), "userScripts"); + QQuickWebEngineScript script; + script.setSourceCode("document.title = 'New title';"); + list.append(&script); + + webEngineView1->setUrl(urlFromTestPath("html/basic_page.html")); + QVERIFY(waitForLoadSucceeded(webEngineView1.data())); + QTRY_COMPARE(webEngineView1->title(), QStringLiteral("New title")); + + webEngineView2->setUrl(urlFromTestPath("html/basic_page.html")); + QVERIFY(waitForLoadSucceeded(webEngineView2.data())); + QTRY_COMPARE(webEngineView2->title(), QStringLiteral("New title")); - delete viewDE; - delete viewEN; + list.clear(); } QTEST_MAIN(tst_QQuickWebEngineView) diff --git a/tests/auto/quick/shared/util.h b/tests/auto/quick/shared/util.h index 674c2da34..dce0afb8e 100644 --- a/tests/auto/quick/shared/util.h +++ b/tests/auto/quick/shared/util.h @@ -98,7 +98,7 @@ inline bool waitForLoadSucceeded(QQuickWebEngineView *webEngineView, int timeout return spy.wait(timeout); } -inline bool waitForLoadFailed(QQuickWebEngineView *webEngineView, int timeout = 10000) +inline bool waitForLoadFailed(QQuickWebEngineView *webEngineView, int timeout = 20000) { LoadSpy loadSpy(webEngineView); QSignalSpy spy(&loadSpy, &LoadSpy::loadFailed); @@ -120,4 +120,26 @@ inline bool waitForViewportReady(QQuickWebEngineView *webEngineView, int timeout #endif } +inline QString bodyInnerText(QQuickWebEngineView *webEngineView) +{ + qRegisterMetaType<QQuickWebEngineView::JavaScriptConsoleMessageLevel>("JavaScriptConsoleMessageLevel"); + QSignalSpy consoleMessageSpy(webEngineView, &QQuickWebEngineView::javaScriptConsoleMessage); + + webEngineView->runJavaScript( + "if (document.body == null)" + " console.log('');" + "else" + " console.log(document.body.innerText);" + ); + + if (!consoleMessageSpy.wait()) + return QString(); + + QList<QVariant> arguments = consoleMessageSpy.takeFirst(); + if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel) + return QString(); + + return arguments.at(1).toString(); +} + #endif /* UTIL_H */ diff --git a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro index 6446cdd7a..e0765736e 100644 --- a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro +++ b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro @@ -1,4 +1,4 @@ include(../tests.pri) QT *= core-private -contains(WEBENGINE_CONFIG, enable_pdf): DEFINES+=QWEBENGINEPAGE_PDFPRINTINGENABLED +contains(WEBENGINE_CONFIG, use_pdf): DEFINES+=QWEBENGINEPAGE_PDFPRINTINGENABLED diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index cde09f5c6..331c15ab8 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -32,6 +32,7 @@ #include <QOpenGLWidget> #include <QPaintEngine> #include <QPushButton> +#include <QRegExp> #include <QScreen> #include <QStateMachine> #include <QtGui/QClipboard> @@ -3713,8 +3714,7 @@ void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures() const QUrl first("http://abcdef.abcdef/"); page.setUrl(first); - QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 1); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 12000); QCOMPARE(page.url(), first); QCOMPARE(page.requestedUrl(), first); QVERIFY(!spy.at(0).first().toBool()); @@ -3723,8 +3723,7 @@ void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures() QVERIFY(first != second); page.load(second); - QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 2); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 12000); QCOMPARE(page.url(), first); QCOMPARE(page.requestedUrl(), second); QVERIFY(!spy.at(1).first().toBool()); @@ -4494,11 +4493,11 @@ void tst_QWebEnginePage::loadFinishedAfterNotFoundError() page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); page.setUrl(QUrl("http://non.existent/url")); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 12000); page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, true); page.setUrl(QUrl("http://another.non.existent/url")); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 12000); } class URLSetter : public QObject { @@ -4690,10 +4689,15 @@ void tst_QWebEnginePage::printToPdf() page.load(QUrl("qrc:///resources/basic_printing_page.html")); QTRY_VERIFY(spy.count() == 1); + QSignalSpy savePdfSpy(&page, SIGNAL(pdfPrintingFinished(const QString&, bool))); QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0)); QString path = tempDir.path() + "/print_1_success.pdf"; page.printToPdf(path, layout); - QTRY_VERIFY(QFile::exists(path)); + QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal"); + + QList<QVariant> successArguments = savePdfSpy.takeFirst(); + QVERIFY2(successArguments.at(0).toString() == path, "File path for first saved PDF does not match arguments"); + QVERIFY2(successArguments.at(1).toBool() == true, "Printing to PDF file failed though it should succeed"); #if !defined(Q_OS_WIN) path = tempDir.path() + "/print_//2_failed.pdf"; @@ -4701,7 +4705,11 @@ void tst_QWebEnginePage::printToPdf() path = tempDir.path() + "/print_|2_failed.pdf"; #endif page.printToPdf(path, QPageLayout()); - QTRY_VERIFY(!QFile::exists(path)); + QTRY_VERIFY2(savePdfSpy.count() == 1, "Printing to PDF file failed without signal"); + + QList<QVariant> failedArguments = savePdfSpy.takeFirst(); + QVERIFY2(failedArguments.at(0).toString() == path, "File path for second saved PDF does not match arguments"); + QVERIFY2(failedArguments.at(1).toBool() == false, "Printing to PDF file succeeded though it should fail"); CallbackSpy<QByteArray> successfulSpy; page.printToPdf(successfulSpy.ref(), layout); @@ -4807,8 +4815,8 @@ void tst_QWebEnginePage::viewSourceURL_data() QUrl testResourceUrl = QUrl(QString("view-source:%1").arg(resourcePath)); QTest::newRow(testResourceUrl.toString().toStdString().c_str()) << testResourceUrl << true << testResourceUrl << QUrl(resourcePath) << testResourceUrl.toString(); - QTest::newRow("view-source:http://non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("http://non.existent/ is not available"); - QTest::newRow("view-source:non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("http://non.existent/ is not available"); + QTest::newRow("view-source:http://non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("non.existent"); + QTest::newRow("view-source:non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("non.existent"); } void tst_QWebEnginePage::viewSourceURL() @@ -4826,7 +4834,7 @@ void tst_QWebEnginePage::viewSourceURL() QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); page.load(userInputUrl); - QTRY_COMPARE(loadFinishedSpy.count(), 1); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count(), 1, 12000); QList<QVariant> arguments = loadFinishedSpy.takeFirst(); QCOMPARE(arguments.at(0).toBool(), loadSucceed); diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 02e1d417e..e51171437 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -38,6 +38,9 @@ #include <QHBoxLayout> #include <QQuickItem> #include <QQuickWidget> +#include <QtWebEngineCore/qwebenginehttprequest.h> +#include <QTcpServer> +#include <QTcpSocket> #include <QStyle> #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \ @@ -91,6 +94,7 @@ private Q_SLOTS: void inputMethodsTextFormat(); void keyboardEvents(); void keyboardFocusAfterPopup(); + void postData(); void softwareInputPanel(); void hiddenText(); @@ -375,29 +379,40 @@ void tst_QWebEngineView::unhandledKeyEventPropagation() parentWidget.show(); QTest::qWaitForWindowExposed(&webView); - QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); - webView.setHtml("<input type='text'/>"); - QTRY_COMPARE(loadSpy.count(), 1); + QSignalSpy loadFinishedSpy(&webView, SIGNAL(loadFinished(bool))); + webView.load(QUrl("qrc:///resources/keyboardEvents.html")); + QVERIFY(loadFinishedSpy.wait()); - evaluateJavaScriptSync(webView.page(), "document.body.firstChild.focus()"); + evaluateJavaScriptSync(webView.page(), "document.getElementById('first_div').focus()"); + QTRY_COMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("first_div")); + + QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Right, QString(), Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Right, QString(), Qt::NoModifier); + // Right arrow key is unhandled thus focus is not changed + QTRY_COMPARE(parentWidget.releaseEvents.size(), 1); + QCOMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("first_div")); + + QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Tab, QString(), Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Tab, QString(), Qt::NoModifier); + // Tab key is handled thus focus is changed + QTRY_COMPARE(parentWidget.releaseEvents.size(), 2); + QCOMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("second_div")); - QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_A, 'a', Qt::NoModifier); - QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_A, 'a', Qt::NoModifier); - QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier); - QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier); QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier); QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier); - - // All this happens asychronously, wait for the last release event to know when we're done. + // Left arrow key is unhandled thus focus is not changed QTRY_COMPARE(parentWidget.releaseEvents.size(), 3); + QCOMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("second_div")); + + // The page will consume the Tab key to change focus between elements while the arrow + // keys won't be used. + QCOMPARE(parentWidget.pressEvents.size(), 2); + QCOMPARE(parentWidget.pressEvents[0].key(), (int)Qt::Key_Right); + QCOMPARE(parentWidget.pressEvents[1].key(), (int)Qt::Key_Left); - // The page will consume the 'a' and the first left key presses, the second left won't be - // used since the cursor will already be at the left end of the text input. // Key releases will all come back unconsumed. - QCOMPARE(parentWidget.pressEvents.size(), 1); - QCOMPARE(parentWidget.pressEvents[0].key(), (int)Qt::Key_Left); - QCOMPARE(parentWidget.releaseEvents[0].key(), (int)Qt::Key_A); - QCOMPARE(parentWidget.releaseEvents[1].key(), (int)Qt::Key_Left); + QCOMPARE(parentWidget.releaseEvents[0].key(), (int)Qt::Key_Right); + QCOMPARE(parentWidget.releaseEvents[1].key(), (int)Qt::Key_Tab); QCOMPARE(parentWidget.releaseEvents[2].key(), (int)Qt::Key_Left); } @@ -900,36 +915,41 @@ void tst_QWebEngineView::focusInternalRenderWidgetHostViewQuickItem() void tst_QWebEngineView::changeLocale() { + QStringList errorLines; QUrl url("http://non.existent/"); QLocale::setDefault(QLocale("de")); QWebEngineView viewDE; - viewDE.setUrl(url); + QSignalSpy loadFinishedSpyDE(&viewDE, SIGNAL(loadFinished(bool))); + viewDE.load(url); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyDE.count(), 1, 12000); - QSignalSpy spyTitleChangedDE(&viewDE, &QWebEngineView::titleChanged); - QVERIFY(spyTitleChangedDE.wait()); - QSignalSpy spyFinishedDE(&viewDE, &QWebEngineView::loadFinished); - QVERIFY(spyFinishedDE.wait()); - QCOMPARE(viewDE.title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString())); + QTRY_VERIFY(!toPlainTextSync(viewDE.page()).isEmpty()); + errorLines = toPlainTextSync(viewDE.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("Diese Website ist nicht erreichbar")); QLocale::setDefault(QLocale("en")); QWebEngineView viewEN; - viewEN.setUrl(url); - - QSignalSpy spyTitleChangedEN(&viewEN, &QWebEngineView::titleChanged); - QVERIFY(spyTitleChangedEN.wait()); - QSignalSpy spyFinishedEN(&viewEN, &QWebEngineView::loadFinished); - QVERIFY(spyFinishedEN.wait()); - QCOMPARE(viewEN.title(), QStringLiteral("%1 is not available").arg(url.toString())); - - viewDE.setUrl(QUrl("about:blank")); - QVERIFY(spyFinishedDE.wait()); - - viewDE.setUrl(url); - - QVERIFY(spyTitleChangedDE.wait()); - QVERIFY(spyFinishedDE.wait()); - QCOMPARE(viewDE.title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString())); + QSignalSpy loadFinishedSpyEN(&viewEN, SIGNAL(loadFinished(bool))); + viewEN.load(url); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyEN.count(), 1, 12000); + + QTRY_VERIFY(!toPlainTextSync(viewEN.page()).isEmpty()); + errorLines = toPlainTextSync(viewEN.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("This site can\u2019t be reached")); + + // Reset error page + viewDE.load(QUrl("about:blank")); + QVERIFY(loadFinishedSpyDE.wait()); + loadFinishedSpyDE.clear(); + + // Check whether an existing QWebEngineView keeps the language settings after changing the default locale + viewDE.load(url); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyDE.count(), 1, 12000); + + QTRY_VERIFY(!toPlainTextSync(viewDE.page()).isEmpty()); + errorLines = toPlainTextSync(viewDE.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QCOMPARE(errorLines.first(), QStringLiteral("Diese Website ist nicht erreichbar")); } void tst_QWebEngineView::inputMethodsTextFormat_data() @@ -1139,6 +1159,137 @@ void tst_QWebEngineView::keyboardFocusAfterPopup() QTRY_COMPARE(evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').value").toString(), QStringLiteral("x")); } +void tst_QWebEngineView::postData() +{ + QMap<QString, QString> postData; + // use reserved characters to make the test harder to pass + postData[QStringLiteral("Spä=m")] = QStringLiteral("ëgg:s"); + postData[QStringLiteral("foo\r\n")] = QStringLiteral("ba&r"); + + QEventLoop eventloop; + + // Set up dummy "HTTP" server + QTcpServer server; + connect(&server, &QTcpServer::newConnection, this, [this, &server, &eventloop, &postData](){ + QTcpSocket* socket = server.nextPendingConnection(); + + connect(socket, &QAbstractSocket::disconnected, this, [&eventloop](){ + eventloop.quit(); + }); + + connect(socket, &QIODevice::readyRead, this, [this, socket, &server, &postData](){ + QByteArray rawData = socket->readAll(); + QStringList lines = QString::fromLocal8Bit(rawData).split("\r\n"); + + // examine request + QStringList request = lines[0].split(" ", QString::SkipEmptyParts); + bool requestOk = request.length() > 2 + && request[2].toUpper().startsWith("HTTP/") + && request[0].toUpper() == "POST" + && request[1] == "/"; + if (!requestOk) // POST and HTTP/... can be switched(?) + requestOk = request.length() > 2 + && request[0].toUpper().startsWith("HTTP/") + && request[2].toUpper() == "POST" + && request[1] == "/"; + + // examine headers + int line = 1; + bool headersOk = true; + for (; headersOk && line < lines.length(); line++) { + QStringList headerParts = lines[line].split(":"); + if (headerParts.length() < 2) + break; + QString headerKey = headerParts[0].trimmed().toLower(); + QString headerValue = headerParts[1].trimmed().toLower(); + + if (headerKey == "host") + headersOk = headersOk && (headerValue == "127.0.0.1") + && (headerParts.length() == 3) + && (headerParts[2].trimmed() + == QString::number(server.serverPort())); + if (headerKey == "content-type") + headersOk = headersOk && (headerValue == "application/x-www-form-urlencoded"); + } + + // examine body + bool bodyOk = true; + if (lines.length() == line+2) { + QStringList postedFields = lines[line+1].split("&"); + QMap<QString, QString> postedData; + for (int i = 0; bodyOk && i < postedFields.length(); i++) { + QStringList postedField = postedFields[i].split("="); + if (postedField.length() == 2) + postedData[QUrl::fromPercentEncoding(postedField[0].toLocal8Bit())] + = QUrl::fromPercentEncoding(postedField[1].toLocal8Bit()); + else + bodyOk = false; + } + bodyOk = bodyOk && (postedData == postData); + } else { // no body at all or more than 1 line + bodyOk = false; + } + + // send response + socket->write("HTTP/1.1 200 OK\r\n"); + socket->write("Content-Type: text/html\r\n"); + socket->write("Content-Length: 39\r\n\r\n"); + if (requestOk && headersOk && bodyOk) + // 6 6 11 7 7 2 = 39 (Content-Length) + socket->write("<html><body>Test Passed</body></html>\r\n"); + else + socket->write("<html><body>Test Failed</body></html>\r\n"); + socket->flush(); + + if (!requestOk || !headersOk || !bodyOk) { + qDebug() << "Dummy HTTP Server: received request was not as expected"; + qDebug() << rawData; + QVERIFY(requestOk); // one of them will yield useful output and make the test fail + QVERIFY(headersOk); + QVERIFY(bodyOk); + } + + socket->close(); + }); + }); + if (!server.listen()) + QFAIL("Dummy HTTP Server: listen() failed"); + + // Manual, hard coded client (commented out, but not removed - for reference and just in case) + /* + QTcpSocket client; + connect(&client, &QIODevice::readyRead, this, [&client, &eventloop](){ + qDebug() << "Dummy HTTP client: data received"; + qDebug() << client.readAll(); + eventloop.quit(); + }); + connect(&client, &QAbstractSocket::connected, this, [&client](){ + client.write("HTTP/1.1 / GET\r\n\r\n"); + }); + client.connectToHost(QHostAddress::LocalHost, server.serverPort()); + */ + + // send the POST request + QWebEngineView view; + QString sPort = QString::number(server.serverPort()); + view.load(QWebEngineHttpRequest::postRequest(QUrl("http://127.0.0.1:"+sPort), postData)); + + // timeout after 10 seconds + QTimer timeoutGuard(this); + connect(&timeoutGuard, &QTimer::timeout, this, [&eventloop](){ + eventloop.quit(); + QFAIL("Dummy HTTP Server: waiting for data timed out"); + }); + timeoutGuard.setSingleShot(true); + timeoutGuard.start(10000); + + // start the test + eventloop.exec(); + + timeoutGuard.stop(); + server.close(); +} + class TestInputContext : public QPlatformInputContext { public: diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index 43a5f2757..9caa1aa68 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -23,34 +23,61 @@ defineTest(runConfigure) { isQtMinimum(5, 8) { include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) QT_FOR_CONFIG += webengine-private + + qtConfig(pepper-plugins): WEBENGINE_CONFIG += use_pepper_plugins + qtConfig(printing-and-pdf): WEBENGINE_CONFIG += use_printing use_pdf qtConfig(proprietary-codecs): WEBENGINE_CONFIG += use_proprietary_codecs qtConfig(spellchecker): WEBENGINE_CONFIG += use_spellchecker + qtConfig(webrtc): WEBENGINE_CONFIG += use_webrtc + qtConfig(embedded): WEBENGINE_CONFIG += embedded_build + qtConfig(system-webp): WEBENGINE_CONFIG += use_system_libwebp + else: WEBENGINE_CONFIG += use_bundled_libwebp + qtConfig(system-opus): WEBENGINE_CONFIG += use_system_opus + else: WEBENGINE_CONFIG += use_bundled_opus + qtConfig(system-ffmpeg): WEBENGINE_CONFIG += use_system_ffmpeg + else: WEBENGINE_CONFIG += use_bundled_ffmpeg + } else { + cross_compile: WEBENGINE_CONFIG += embedded_build } + isQtMinimum(5, 9) { + qtConfig(appstore-compliant): WEBENGINE_CONFIG += use_appstore_compliant_code + linux: WEBENGINE_CONFIG += use_gn + macos: WEBENGINE_CONFIG += use_gn + win32: WEBENGINE_CONFIG += use_gn + } + !use?(gn): skipBuild("Chromium 55 and new can only be built with GN") linux { QT_FOR_CONFIG += gui-private !config_khr:skipBuild("khronos development headers appear to be missing (mesa/libegl1-mesa-dev)") REQUIRED_PACKAGES = dbus-1 fontconfig - !cross_compile: qtConfig(xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst + !contains(WEBENGINE_CONFIG, embedded_build): qtConfig(xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xtst qtConfig(pulseaudio): REQUIRED_PACKAGES += libpulse qtConfig(system-png): REQUIRED_PACKAGES += libpng qtConfig(system-harfbuzz) { packagesExist("\'harfbuzz >= 1.2.0\'"): WEBENGINE_CONFIG += use_system_harfbuzz else: log("System harfbuzz is too old (min. version 1.2). Using Chromium's copy.$${EOL}") } - !cross_compile: REQUIRED_PACKAGES += libpci + qtConfig(glib) { + packagesExist("\'glib-2.0 >= 2.32.0\'"): WEBENGINE_CONFIG += use_glib + else: skipBuild("System glib is too old (min. version 2.32).$${EOL}") + } for(package, $$list($$REQUIRED_PACKAGES)) { !packagesExist($$package):skipBuild("Unmet dependency: $$package") } packagesExist(minizip, zlib): WEBENGINE_CONFIG += use_system_minizip use_system_zlib else: log("System zlib or minizip not found. Using Chromium's copies.$${EOL}") - packagesExist(libwebp,libwebpdemux): WEBENGINE_CONFIG += use_system_libwebp use_system_libwebpdemux - else: log("System libwebp or libwebpdemux not found. Using Chromium's copies.$${EOL}") + !isQtMinimum(5, 8) { + packagesExist(libwebp,libwebpdemux): WEBENGINE_CONFIG += use_system_libwebp use_system_libwebpdemux + else: log("System libwebp or libwebpdemux not found. Using Chromium's copies.$${EOL}") + packagesExist(opus): WEBENGINE_CONFIG += use_system_opus + else: log("System opus not found. Using Chromium's copy.$${EOL}") + } packagesExist(libxml-2.0,libxslt): WEBENGINE_CONFIG += use_system_libxslt use_system_libxml2 else: log("System libxml2 or libxslt not found. Using Chromium's copies.$${EOL}") - for(package, $$list("libevent jsoncpp opus protobuf")) { + for(package, $$list("libevent jsoncpp protobuf")) { packagesExist($$package): WEBENGINE_CONFIG += use_system_$$package else { log("System $$package not found. Using Chromium's copy.$${EOL}") @@ -80,14 +107,11 @@ defineTest(runConfigure) { WEBENGINE_CONFIG += use_bundled_snappy } - !cross_compile { + !contains(WEBENGINE_CONFIG, embedded_build) { packagesExist(nss): WEBENGINE_CONFIG += use_nss else: log("System NSS not found, BoringSSL will be used.$${EOL}") } } - !cross_compile { - WEBENGINE_CONFIG += enable_pdf - } isEmpty(skipBuildReason): { cache(CONFIG, add, $$list(webengine_successfully_configured)) @@ -110,21 +134,23 @@ defineTest(runConfigure) { log(" ICU ................................ Using internal copy (Default, force system ICU with WEBENGINE_CONFIG+=use_system_icu)$${EOL}") WEBENGINE_CONFIG += use_bundled_icu } - use?(system_ffmpeg) { - packagesExist("libavcodec libavformat libavutil") { - packagesExist("libwebp, libwebpdemux, opus, \'vpx >= 1.4\'"){ - log(" FFMPEG ............................. Using system version$${EOL}") + !isQtMinimum(5, 8) { + use?(system_ffmpeg) { + packagesExist("libavcodec libavformat libavutil") { + packagesExist("libwebp, libwebpdemux, opus, \'vpx >= 1.4\'"){ + log(" FFMPEG ............................. Using system version$${EOL}") + } else { + log(" FFMPEG ............................. Conflicting FFMPEG dependencies$${EOL}") + skipBuild("Unmet dependencies: opus, vpx, libwebp, libwebpdemux") + } } else { - log(" FFMPEG ............................. Conflicting FFMPEG dependencies$${EOL}") - skipBuild("Unmet dependencies: opus, vpx, libwebp, libwebpdemux") + log(" FFMPEG ............................. System FFMPEG not found$${EOL}") + skipBuild("Unmet dependencies: libavcodec, libavformat, libavutil") } } else { - log(" FFMPEG ............................. System FFMPEG not found$${EOL}") - skipBuild("Unmet dependencies: libavcodec, libavformat, libavutil") + log(" FFMPEG ............................. Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}") + WEBENGINE_CONFIG += use_bundled_ffmpeg } - } else { - log(" FFMPEG ............................. Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}") - WEBENGINE_CONFIG += use_bundled_ffmpeg } for(config, WEBENGINE_CONFIG) { match = $$find(config, "^use_system_") diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf index 6545ef791..b4965129c 100644 --- a/tools/qmake/mkspecs/features/functions.prf +++ b/tools/qmake/mkspecs/features/functions.prf @@ -59,10 +59,10 @@ defineTest(isPlatformSupported) { skipBuild("Using XCode version $$QMAKE_XCODE_VERSION, but at least version 5.1 is required to build Qt WebEngine.") return(false) } - # We require OS X 10.9 (darwin version 13.0.0) or newer + # We require OS X 10.0 (darwin version 14.0.0) or newer darwin_major_version = $$section(QMAKE_HOST.version, ., 0, 0) - lessThan(darwin_major_version, 13) { - skipBuild("Qt WebEngine requires OS X version 10.9 or newer.") + lessThan(darwin_major_version, 14) { + skipBuild("Qt WebEngine requires OS X version 10.10 or newer.") return(false) } !isMinOSXSDKVersion(10, 10): { @@ -222,14 +222,26 @@ defineTest(isSanitizerLinuxClangVersionSupported) { defineTest(isGCCVersionSupported) { # The below will work for gcc 4.7 and up and also match gcc 5 - greaterThan(QT_GCC_MINOR_VERSION, 6):return(true) + CONFIG(release, debug|release): greaterThan(QT_GCC_MINOR_VERSION, 6):return(true) greaterThan(QT_GCC_MAJOR_VERSION, 4):return(true) - skipBuild("Using gcc version "$$QT_GCC_MAJOR_VERSION"."$$QT_GCC_MINOR_VERSION", but at least gcc version 4.7 is required to build Qt WebEngine.") + + # We need GCC 4.9 for debug builds because Skia handles SIMD inlines in headers poorly. + greaterThan(QT_GCC_MINOR_VERSION, 8):return(true) + CONFIG(debug, debug|release) { + skipBuild("Using gcc version "$$QT_GCC_MAJOR_VERSION"."$$QT_GCC_MINOR_VERSION", but at least gcc version 4.9 is required to build debug versions of Qt WebEngine.") + } else { + skipBuild("Using gcc version "$$QT_GCC_MAJOR_VERSION"."$$QT_GCC_MINOR_VERSION", but at least gcc version 4.7 is required to build Qt WebEngine.") + } return(false) } +defineTest(isDeveloperBuild) { + qtConfig(private_tests): return(true) # enabled for developer-build + return(false) +} + defineTest(isQMLTestSupportApiEnabled) { - qtConfig(private_tests): return(true) # enable for developer-build + isDeveloperBuild(): return(true) contains(QT_BUILD_PARTS, tests): return(true) contains(WEBENGINE_CONFIG, testsupport): return(true) return(false) @@ -385,24 +397,49 @@ defineTest(use?) { return(false) } -defineReplace(findOrBuildNinja) { - # If NINJA_PATH env var is set, prefer that. - # Fallback to locating our own bootstrapped ninja. - out = $(NINJA_PATH) - !exists($$out) { +defineReplace(ninjaPath) { src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT") - out = $$shadowed($$absolute_path(ninja/ninja, $$src_3rd_party_dir)) win32: out = $${out}.exe + return($$out) +} + +defineReplace(gnPath) { + src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT") + out = $$shadowed($$absolute_path(chromium/tools/gn/out/Release/gn, $$src_3rd_party_dir)) - # If we did not find ninja, then we bootstrap it. - !exists($$out) { - mkpath($$dirname(out)) - ninja_configure = $$absolute_path(ninja/configure.py, $$src_3rd_party_dir) - system("cd $$system_quote($$system_path($$dirname(out))) && python $$system_quote($$system_path($$ninja_configure)) --bootstrap") + win32: out = $${out}.exe + return($$out) +} + +defineReplace(gnArgs) { + linux { + contains(WEBENGINE_CONFIG, embedded_build): include($$QTWEBENGINE_ROOT/src/core/config/embedded_linux.pri) + else: include($$QTWEBENGINE_ROOT/src/core/config/desktop_linux.pri) } - } - return($$system_path($$out)) + macos: include($$QTWEBENGINE_ROOT/src/core/config/mac_osx.pri) + win32: include($$QTWEBENGINE_ROOT/src/core/config/windows.pri) + isEmpty(gn_args): error(No gn_args found please make sure you have valid configuration.) + return($$gn_args) +} + +defineReplace(gnArch) { + qtArch = $$1 + contains(qtArch, "i386"): return(x86) + contains(qtArch, "x86_64"): return(x64) + contains(qtArch, "arm"): return(arm) + contains(qtArch, "arm64"): return(arm64) + contains(qtArch, "mips"): return(mipsel) + contains(qtArch, "mips64"): return(mips64el) + return(unknown) +} + +defineReplace(gnOS) { + macos: return(mac) + win32: return(win) + linux: return(linux) + error(Unsupported platform) + return(unknown) } defineTest(skipBuild) { diff --git a/tools/qmake/mkspecs/features/gn_generator.prf b/tools/qmake/mkspecs/features/gn_generator.prf new file mode 100644 index 000000000..57c53935c --- /dev/null +++ b/tools/qmake/mkspecs/features/gn_generator.prf @@ -0,0 +1,235 @@ +load(moc) +load(resources) + +defineReplace(getTargetType) { + equals(TEMPLATE, "app"):return("executable") + equals(TEMPLATE, "lib") { + CONFIG(static): return("static_library") + return("shared_library") + } + return("none") +} + +defineReplace(filter_flag_values) { + value_to_check = $$1 + macos:equals(value_to_check, "$(EXPORT_ARCH_ARGS)") { + # EXPORT_ARCH_ARGS comes from qtbase/mkspecs/features/mac/default_post.prf which is a way + # to figure out the architectures to pass to the compiler at Makefile time. Because this + # variable expansion is not supported by GN, we filter it out. GN takes care of assigning + # the architecture itself. + return("") + } + return($$value_to_check) +} + +isEmpty(GN_FILE): GN_FILE = $$system_path($$_PRO_FILE_PWD_/BUILD.gn) +isEmpty(GN_RUN_BINARY_SCRIPT): GN_RUN_BINARY_SCRIPT = "//build/gn_run_binary.py" +isEmpty(GN_FIND_MOCABLES_SCRIPT): GN_FIND_MOCABLES_SCRIPT = "//build/gn_find_mocables.py" + +# MOC SETUP + +GN_CONTENTS += "moc_source_h_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\"," +GN_CONTENTS += " [ \"$$_PRO_FILE_PWD_\"," +for (headerfile, HEADERS): GN_CONTENTS += " \"$$GN_SRC_DIR/$$headerfile\"," +GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\ + ")" +GN_CONTENTS += "moc_source_cpp_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\"," +GN_CONTENTS += " [ \"$$_PRO_FILE_PWD_\"," +for (sourcefile, SOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," +GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\ + ")" + +DEFINES_LIST = $$join(DEFINES, " -D", "-D") +INCLUDE_LIST = $$join(INCLUDEPATH, " -I", "-I") + +# we don't generate a moc_predef file yet. +MOC_PREDEF_FILE = +MOC_COMMAND = $$clean_path($$mocCmdBase()) +MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(DEFINES)"), $$DEFINES_LIST) +MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(INCPATH)"), $$INCLUDE_LIST) +MOC_COMMAND = $$eval($$list($$MOC_COMMAND)) + +GN_CONTENTS += "if (moc_source_h_files != []) {" +GN_CONTENTS += " action_foreach(\"generate_h_mocs\") {"\ + " script = \"$$GN_RUN_BINARY_SCRIPT\"" +GN_CONTENTS += " sources = moc_source_h_files" \ + " outputs = [ \"$target_gen_dir/.moc/moc_{{source_name_part}}.cpp\" ]" +GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ + " args = [" +for(token, MOC_COMMAND): GN_CONTENTS += " \"$$replace(token,\",\\\")\"," +GN_CONTENTS += " \"{{source}}\"," \ + " \"-o\"," \ + " rebase_path(\"$target_gen_dir/.moc/moc_{{source_name_part}}.cpp\")"\ + " ]" +GN_CONTENTS += " }" +GN_CONTENTS += "}" +GN_CONTENTS += "if (moc_source_cpp_files != []) {" +GN_CONTENTS += " action_foreach(\"generate_cpp_mocs\") {"\ + " script = \"$$GN_RUN_BINARY_SCRIPT\"" +GN_CONTENTS += " sources = moc_source_cpp_files" \ + " outputs = [ \"$target_gen_dir/.moc/{{source_name_part}}.moc\" ]" +GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ + " args = [" +for(token, MOC_COMMAND): GN_CONTENTS += " \"$$replace(token,\",\\\")\"," +GN_CONTENTS += " \"{{source}}\"," \ + " \"-o\"," \ + " rebase_path(\"$target_gen_dir/.moc/{{source_name_part}}.moc\")"\ + " ]" +GN_CONTENTS += " }" +GN_CONTENTS += "}" + +# RESOURCES SETUP + +CLEAN_QMAKE_RCC = $$clean_path($$QMAKE_RCC) + +GN_CONTENTS += "action_foreach(\"generate_resources\") {"\ + " script = \"$$GN_RUN_BINARY_SCRIPT\"" +GN_CONTENTS += " sources = [" +for (sourcefile, RESOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," +GN_CONTENTS += " ]" \ + " outputs = [ \"$target_gen_dir/.rcc/qrc_{{source_name_part}}.cpp\" ]" +GN_CONTENTS += " inputs = [ \"$$system_path($$_PRO_FILE_)\" ]" \ + " args = [" \ + " \"$$replace(CLEAN_QMAKE_RCC,\",\\\")\"," +for(resource_flag, $$QMAKE_RESOURCE_FLAGS): GN_CONTENTS += " \"$$resource_flag\"" +GN_CONTENTS += " \"-name\"," \ + " \"{{source_name_part}}\"," \ + " \"{{source}}\"," \ + " \"-o\"," \ + " rebase_path(\"$target_gen_dir/.rcc/qrc_{{source_name_part}}.cpp\")"\ + " ]" +GN_CONTENTS += "}" + +# TARGET SETUP + +TARGET_TYPE = $$getTargetType() + +GN_CONTENTS += "$${TARGET_TYPE}(\"$$TARGET\") {" +!isEmpty(GN_CREATE_PRI): GN_CONTENTS += " create_pri_file = $$GN_CREATE_PRI" +!isEmpty(GN_IMPORTS) { +for (imp, GN_IMPORTS): GN_CONTENTS += " import(\"$$imp\")" +} + +!isEmpty(QMAKE_CFLAGS) { + GN_CONTENTS += " cflags = [" + for(flag, QMAKE_CFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," + GN_CONTENTS += " ]" +} + +!isEmpty(QMAKE_FRAMEWORKPATH) { + GN_CONTENTS += " cflags += [" + for(path, QMAKE_FRAMEWORKPATH): GN_CONTENTS += " \"-F$$path\"," + GN_CONTENTS += " ]" +} + +# Stop the barrage of unused variables warnings. +gcc|clang { + QMAKE_CXXFLAGS += "-Wno-unused-parameter" + QMAKE_CXXFLAGS += "-Wno-unused-variable" +} + +!isEmpty(QMAKE_CXXFLAGS) { + GN_CONTENTS += " cflags_cc = [" + for(flag, QMAKE_CXXFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," + GN_CONTENTS += " ]" +} + +GN_CONTENTS += " if (!defined(defines)) {"\ + " defines = []"\ + " }" +GN_CONTENTS += " defines += [" +# Remove single quotes around function macro defines, so that GN doesn't escape them, thus breaking +# the macro. +# Also add a layer of escaping for double quotes. +for (define, DEFINES): { + define = $$replace(define,\",\\\") + define = $$replace(define,\',) + GN_CONTENTS += " \"$$define\"," +} +!isEmpty(QMAKE_LIBDIR_EGL): + GN_CONTENTS += " \"QT_LIBDIR_EGL=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_EGL, $$[QT_SYSROOT])\\\"\"," +!isEmpty(QMAKE_LIBDIR_OPENGL_ES2) + GN_CONTENTS += " \"QT_LIBDIR_GLES2=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_OPENGL_ES2, $$[QT_SYSROOT])\\\"\"," +GN_CONTENTS += " ]" + +# Source files to compile +GN_CONTENTS += " sources = [" +for (sourcefile, SOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\"," +for (headerfile, HEADERS): GN_CONTENTS += " \"$$GN_SRC_DIR/$$headerfile\"," +GN_CONTENTS += " ]" + +# Add Sources generated by rcc from qrc files. +!isEmpty(RESOURCES): GN_CONTENTS += " sources += get_target_outputs(\":generate_resources\")" + +GN_CONTENTS += " if (!defined(include_dirs)) {"\ + " include_dirs = []"\ + " }" +GN_CONTENTS += " include_dirs += [" +for (path, INCLUDEPATH): GN_CONTENTS += " \"$$path\"," +GN_CONTENTS += " rebase_path(\"$target_gen_dir/.moc/\")" +GN_CONTENTS += " ]" + +GN_CONTENTS += " if (!defined(ldflags)) {"\ + " ldflags = []"\ + " }" +GN_CONTENTS += " ldflags += [" +for (flag, QMAKE_LFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," +for (flag, GN_FLAGS): GN_CONTENTS += " \"$$flag\"," +!isEmpty(QMAKE_RPATHDIR) { + for (rpath, QMAKE_RPATHDIR) { + macos: GN_CONTENTS += " \"-Wl,-rpath,$${rpath}\"," + else:unix: GN_CONTENTS += " \"-Wl,-rpath=$${rpath}\"," + } +} +!isEmpty(QMAKE_RPATHLINKDIR): GN_CONTENTS += " \"-Wl,-rpath-link=$${QMAKE_RPATHLINKDIR}\"," +GN_CONTENTS += " ]" + +GN_CONTENTS += " if (!defined(lib_dirs)) {"\ + " lib_dirs = []"\ + " }" +GN_CONTENTS += " lib_dirs += [" +lib_dirs = $$find(LIBS, ^-L.*) +lib_dirs = $$unique(lib_dirs) +for (lib_dir, lib_dirs): GN_CONTENTS += " \"$$replace(lib_dir, -L, )\"," +GN_CONTENTS += " ]" + +GN_CONTENTS += " if (!defined(libs)) {"\ + " libs = []"\ + " }" +GN_CONTENTS += " libs += [" +for (lib, GN_LIBS): GN_CONTENTS += " \"$$lib\"," +libs = $$find(LIBS, ^-l.*) +libs = $$unique(libs) +for (lib, libs): GN_CONTENTS += " \"$$replace(lib, -l, )\"," +GN_CONTENTS += " ]" + +GN_CONTENTS += " if (!defined(deps)) {"\ + " deps = []"\ + " }" +GN_CONTENTS += " deps += [" +!isEmpty(RESOURCES): GN_CONTENTS += " \":generate_resources\"," +GN_CONTENTS += " ]" +GN_CONTENTS += " if (moc_source_h_files != []) {" +GN_CONTENTS += " deps += [" +GN_CONTENTS += " \":generate_h_mocs\"," +GN_CONTENTS += " ]" +# Add moc output files to compile +GN_CONTENTS += " sources += get_target_outputs(\":generate_h_mocs\")" +GN_CONTENTS += " }" +GN_CONTENTS += " if (moc_source_cpp_files != []) {" +GN_CONTENTS += " deps += [" +GN_CONTENTS += " \":generate_cpp_mocs\"," +GN_CONTENTS += " ]" +GN_CONTENTS += " }" +GN_CONTENTS += "}" +!isEmpty(GN_INCLUDES) { + for (inc, GN_INCLUDES): GN_CONTENTS += $$cat($$inc,lines) +} + +build_pass|!debug_and_release: write_file($$GN_FILE, GN_CONTENTS) + +# The generated Makefile shouldn't build anything by itself, just re-run qmake if necessary +TEMPLATE = aux +SOURCES = +HEADERS = +RESOURCES = diff --git a/tools/scripts/gn_find_mocables.py b/tools/scripts/gn_find_mocables.py new file mode 100644 index 000000000..d97dcb534 --- /dev/null +++ b/tools/scripts/gn_find_mocables.py @@ -0,0 +1,68 @@ +############################################################################# +## +## 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: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$ +## +############################################################################# + +import re +import sys +import os + +mocables = set() +includedMocs = set() +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 + if "/*" in line: + inBlockComment = True + if inBlockComment and "*/" in line: + inBlockComment = False + if line.find("*/") != len(line) - 3: + line = line[line.find("*/")+2:] + else: + continue + if inBlockComment: + continue + #simple comments handling + if "//" in line: + line = line.partition("//")[0] + if re.match(".*Q_OBJECT", line): + mocables.add(f) + im = re.search('#include "(moc_\w+.cpp)"', line) + if im: + includedMocs.add(im.group(1)) + +for mocable in includedMocs: + print "Found included moc: " + mocable + +assert len(includedMocs) == 0 , "Included mocs are not supported !" + +for mocable in mocables: + print mocable +sys.exit(0) diff --git a/tools/scripts/gn_run_binary.py b/tools/scripts/gn_run_binary.py new file mode 100644 index 000000000..5debf02ab --- /dev/null +++ b/tools/scripts/gn_run_binary.py @@ -0,0 +1,33 @@ +############################################################################# +## +## 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: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$ +## +############################################################################# + + +import sys +import subprocess + +sys.exit(subprocess.call(sys.argv[1:])) diff --git a/tools/scripts/init-repository.py b/tools/scripts/init-repository.py index 9fd951be4..dc5cdb8ce 100755 --- a/tools/scripts/init-repository.py +++ b/tools/scripts/init-repository.py @@ -80,6 +80,7 @@ def updateLastChange(): print 'updating LASTCHANGE files' subprocess.call(['python', 'build/util/lastchange.py', '-o', 'build/util/LASTCHANGE']) subprocess.call(['python', 'build/util/lastchange.py', '-s', 'third_party/WebKit', '-o', 'build/util/LASTCHANGE.blink']) + subprocess.call(['python', 'build/util/lastchange.py', '-m', 'SKIA_COMMIT_HASH', '-s', 'third_party/skia', '--header', 'skia/ext/skia_commit_hash.h']) os.chdir(currentDir) def initUpstreamSubmodules(): diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 93575d821..7af70bf22 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -58,7 +58,7 @@ def isInChromiumBlacklist(file_path): if file_path.endswith('.gyp') or file_path.endswith('.gypi') or file_path.endswith('.isolate'): return False # We do need all the gn file. - if file_path.endswith('.gn') or file_path.endswith('.gni') or file_path.endswith('typemap') or \ + if file_path.endswith('.gn') or file_path.endswith('.gni') or file_path.endswith('.typemap') or \ file_path.endswith('.mojom'): return False if ( '_jni' in file_path @@ -76,10 +76,8 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('android_webview') or file_path.startswith('apps/') or file_path.startswith('ash/') - or file_path.startswith('athena') - or file_path.startswith('base/android/java') + or file_path.startswith('base/android') or file_path.startswith('breakpad') - or file_path.startswith('build/android/') or file_path.startswith('buildtools/clang_format/script') or (file_path.startswith('chrome/') and not file_path.startswith('chrome/VERSION') and @@ -91,8 +89,8 @@ def isInChromiumBlacklist(file_path): not '/renderer/resources/' in file_path and not 'repack_locales' in file_path and not 'third_party/chromevox' in file_path and - not 'media/desktop_media_list.h' in file_path and - not 'media/desktop_streams_registry.' in file_path and + not 'media/webrtc/desktop_media_list.h' in file_path and + not 'media/webrtc/desktop_streams_registry.' in file_path and not 'common/chrome_constants.' in file_path and not 'common/chrome_paths' in file_path and not 'common/chrome_switches.' in file_path and @@ -113,21 +111,20 @@ def isInChromiumBlacklist(file_path): not file_path.endswith('.json') and not file_path.endswith('chrome_version.rc.version')) or file_path.startswith('chrome_frame') + or file_path.startswith('chromecast') or file_path.startswith('chromeos') - or file_path.startswith('cloud_print') or file_path.startswith('components/chrome_apps/') or file_path.startswith('components/cronet/') or file_path.startswith('components/drive/') or file_path.startswith('components/invalidation/') or file_path.startswith('components/gcm_driver/') - or file_path.startswith('components/mus/') or file_path.startswith('components/nacl/') or file_path.startswith('components/omnibox/') or file_path.startswith('components/policy/') or file_path.startswith('components/proximity_auth/') or (file_path.startswith('components/resources/terms/') and not file_path.endswith('terms_chromium.html')) or file_path.startswith('components/rlz/') - or file_path.startswith('components/sync_driver/') + or file_path.startswith('components/sync/') or file_path.startswith('components/test/') or file_path.startswith('components/test_runner/') or file_path.startswith('components/translate/') @@ -143,7 +140,6 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('net/android/java') or file_path.startswith('remoting') or file_path.startswith('rlz') - or file_path.startswith('sync') or file_path.startswith('testing/android') or file_path.startswith('testing/buildbot') or file_path.startswith('third_party/WebKit/LayoutTests') @@ -168,6 +164,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/cython') or file_path.startswith('third_party/deqp') or file_path.startswith('third_party/elfutils') + or file_path.startswith('third_party/freetype-android') or file_path.startswith('third_party/google_input_tools') or file_path.startswith('third_party/gperf') or file_path.startswith('third_party/gnu_binutils') @@ -298,6 +295,7 @@ def exportChromium(): # Add LASTCHANGE files which are not tracked by git. files.append('build/util/LASTCHANGE') files.append('build/util/LASTCHANGE.blink') + files.append('skia/ext/skia_commit_hash.h') print 'copying files to ' + third_party_chromium for i in xrange(len(files)): printProgress(i+1, len(files)) diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index e481f0ed0..b80efff34 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -38,9 +38,9 @@ import json import urllib2 import git_submodule as GitSubmodule -chromium_version = '53.0.2785.148' -chromium_branch = '2785' -ninja_version = 'v1.7.1' +chromium_version = '55.0.2883.105' +chromium_branch = '2883' +ninja_version = 'v1.7.2' json_url = 'http://omahaproxy.appspot.com/all.json' |