diff options
92 files changed, 3581 insertions, 593 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..5799dafa3 100644 --- a/configure.json +++ b/configure.json @@ -1,11 +1,16 @@ { "module": "webengine", + "depends": [ + "printsupport" + ], "testDir": "tools/qmake/config.tests", "commandline": { "options": { "alsa": "boolean", + "pepper-plugins": "boolean", + "printing-and-pdf": "boolean", "proprietary-codecs": "boolean", "pulseaudio": "boolean", "spellchecker": "boolean" @@ -28,6 +33,17 @@ } }, + "tests" : { + "ninja": { + "label": "system ninja", + "type": "detectNinja" + }, + "gn": { + "label": "system gn", + "type": "detectGn" + } + }, + "features": { "alsa": { "label": "ALSA", @@ -40,6 +56,19 @@ "condition": "libs.pulseaudio", "output": [ "privateFeature" ] }, + "pepper-plugins": { + "label": "Pepper Plugins", + "autoDetect": "!features.cross_compile", + "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.cross_compile", + "purpose": "Enables printing and output to PDF", + "output": [ "privateFeature" ] + }, "proprietary-codecs": { "label": "Proprietary Codecs", "autoDetect": false, @@ -50,6 +79,17 @@ "label": "Spellchecker", "purpose": "Enables the use of Chromium's spellchecker", "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 +97,11 @@ { "section": "Qt WebEngine", "entries": [ + "pepper-plugins", + "printing-and-pdf", "proprietary-codecs", "spellchecker", + "system-ninja", { "type": "feature", "args": "alsa", diff --git a/configure.pri b/configure.pri new file mode 100644 index 000000000..b6693aecf --- /dev/null +++ b/configure.pri @@ -0,0 +1,25 @@ +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) +} diff --git a/src/3rdparty b/src/3rdparty -Subproject 965b67f25e8af81ce1313287fe842f7a83e7d5e +Subproject 0fa2e061c8209c544f461961fae6887b7a22e3b 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_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/config/common.pri b/src/core/config/common.pri index b5bb23684..7cdf34623 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -1,15 +1,70 @@ # 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 \ + enable_remoting=false \ + enable_nacl=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 + } + +} 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 + } +} diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 23044619b..e8db4248f 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -1,21 +1,29 @@ -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 += \ + is_clang=false \ + use_sysroot=false + + use?(icecc) { + gn_args += use_debug_fission=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..08c8c1661 100644 --- a/src/core/config/embedded_linux.pri +++ b/src/core/config/embedded_linux.pri @@ -9,16 +9,12 @@ 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 \ @@ -39,6 +35,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..8509c0c8e 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -2,6 +2,44 @@ include(common.pri) include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) QT_FOR_CONFIG += gui-private webengine-private +use?(gn) { + gn_args += \ + use_gconf=false \ + use_gio=false \ + use_kerberos=false \ + linux_use_bundled_binutils=false + + #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 + qtConfig(system-harfbuzz): use?(system_harfbuzz): gn_args += use_system_harfbuzz=true + !qtConfig(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 + } + + #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_flag=false + #use?(system_ffmpeg): gn_args += use_system_ffmpeg=true + #use?(system_protobuf): gn_args += use_system_protobuf=true + + #gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): gn_args += no_delete_null_pointer_checks=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..e52051b0c 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -19,25 +19,42 @@ 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}\" + + 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..334675481 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -5,11 +5,7 @@ include(common.pri) 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()}\"" @@ -21,10 +17,18 @@ GYP_ARGS += "-D perl_exe=\"perl.exe\" -D bison_exe=\"bison.exe\" -D gperf_exe=\" GYP_ARGS += "--no-parallel" 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 { diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 787586540..f9b6f31d8 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -386,7 +386,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) diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index 095e54caa..80d4e9827 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/core.pro b/src/core/core.pro index a205d39a0..42906cbca 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -3,39 +3,72 @@ 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_api \ + core_headers \ + core_generator \ + core_module \ + gn_run +} 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 += gyp_run \ + core_api \ + core_module \ + 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 + } +} diff --git a/src/core/core_gyp_generator.pro b/src/core/core_generator.pro index a09683ba6..ed47a47e9 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_generator.pro @@ -1,10 +1,9 @@ -# 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) +} else { + include(core_gyp_config.pri) +} TEMPLATE = lib @@ -13,7 +12,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" } @@ -45,6 +52,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 +83,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 +90,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 +158,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 +166,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 +194,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..a7853e524 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,30 @@ 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 + unix { + 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 + } else { + OBJECTS = $$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 +} + + LIBS_PRIVATE += -L$$api_library_path CONFIG *= no_smart_library_merge osx { @@ -44,7 +70,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) { @@ -109,4 +140,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 baf064025..4bc83163f 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -171,6 +171,245 @@ 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++); + 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(); + imageNode->setTargetRect(rect); + imageNode->setInnerTargetRect(rect); + imageNode->setTexture(layer); + imageNode->update(); + + layerChain->appendChildNode(imageNode); + m_sceneGraphNodes->append(imageNode); + } + + 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; @@ -513,7 +752,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 +823,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 +844,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_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 +883,168 @@ 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(); + 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; - - // 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 +1055,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()); 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/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/gn_run.pro b/src/core/gn_run.pro new file mode 100644 index 000000000..534f0c7b3 --- /dev/null +++ b/src/core/gn_run.pro @@ -0,0 +1,63 @@ +isQtMinimum(5, 8) { + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private +} + +TEMPLATE = aux + +build_pass|!debug_and_release { + + macos: include(config/mac_osx.pri) + linux: include(config/desktop_linux.pri) + isEmpty(gn_args): error(No gn_args found please make sure you have valid configuration.) + + ninja_binary = ninja + gn_binary = gn + + runninja.target = run_ninja + rungn.target = run_gn + + !qtConfig(system-ninja) { + ninja_binary = $$shell_quote($$shell_path($$ninjaPath())) + buildninja.target = build_ninja + buildninja.commands = $$buildNinja() + QMAKE_EXTRA_TARGETS += buildninja + runninja.depends = buildninja + } + + 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())) + buildgn.target = build_gn + buildgn.commands = $$buildGn($$gn_args) + !qtConfig(system-ninja) { + buildgn.depends = buildninja + rungn.depends = buildninja + } + QMAKE_EXTRA_TARGETS += buildgn + } + + 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 = $$gn_binary gen $$gn_build_root --args=$$gn_args --root=$$gn_src_root + QMAKE_EXTRA_TARGETS += rungn + + runninja.commands = $$ninja_binary \$\(NINJAFLAGS\) -v -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 +} else { + # 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..c583845e9 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -2,6 +2,11 @@ # 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 { @@ -148,13 +153,24 @@ 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())) + buildninja.target = build_ninja + buildninja.commands = $$buildNinja() + QMAKE_EXTRA_TARGETS += buildninja + runninja.depends = buildninja + } + + 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/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/qtwebengine.gni b/src/core/qtwebengine.gni new file mode 100644 index 000000000..4e561e7a9 --- /dev/null +++ b/src/core/qtwebengine.gni @@ -0,0 +1,47 @@ +chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("//chrome/VERSION"), + "-t", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"], + "list lines") + +declare_args() { + use_qt = true +} + +include_dirs = [ + "//skia/config", + "//third_party/skia/include/core" +] + +deps = [ + "//base", + "//components/cdm/renderer", + "//components/devtools_http_handler", + "//components/error_page/common", + "//components/keyed_service/content", + "//components/visitedlink/browser", + "//components/visitedlink/renderer", + "//components/web_cache/browser", + "//components/web_cache/public/interfaces", + "//components/web_cache/renderer", + "//content/public/app:browser", + "//content/public/browser", + "//content/public/common", + "//net:net_browser_services", + "//services/shell/public/cpp", + "//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"] +} + +# fixme: +defines = [ + "QTWEBENGINEPROCESS_NAME=\"QtWebEngineProcess\"", + "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..e3cd42169 --- /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_name = "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..2d3503e98 --- /dev/null +++ b/src/core/qtwebengine_sources.gni @@ -0,0 +1,128 @@ +source_set("qtwebengine_sources") { + include_dirs = [ + "//skia/config", + "//third_party/skia/include/core" + ] + deps = [] + sources = [ + "//chrome/browser/media/desktop_media_list.h", + "//chrome/browser/media/desktop_streams_registry.cc", + "//chrome/browser/media/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_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_spellcheck) { + sources += [ + "//chrome/browser/spellchecker/feedback.cc", + "//chrome/browser/spellchecker/feedback.h", + "//chrome/browser/spellchecker/feedback_sender.cc", + "//chrome/browser/spellchecker/feedback_sender.h", + "//chrome/browser/spellchecker/misspelling.cc", + "//chrome/browser/spellchecker/misspelling.h", + "//chrome/browser/spellchecker/spellcheck_action.cc", + "//chrome/browser/spellchecker/spellcheck_action.h", + "//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_host_metrics.cc", + "//chrome/browser/spellchecker/spellcheck_host_metrics.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_platform_mac.mm", + "//chrome/browser/spellchecker/spellcheck_service.cc", + "//chrome/browser/spellchecker/spellcheck_service.h", + "//chrome/browser/spellchecker/spelling_service_client.cc", + "//chrome/browser/spellchecker/spelling_service_client.h", + "//chrome/browser/spellchecker/word_trimmer.cc", + "//chrome/browser/spellchecker/word_trimmer.h", + "//chrome/common/common_message_generator.cc", + "//chrome/common/pref_names.cc", + "//chrome/common/pref_names.h", + "//chrome/common/spellcheck_bdict_language.h", + "//chrome/common/spellcheck_common.cc", + "//chrome/common/spellcheck_common.h", + "//chrome/common/spellcheck_marker.h", + "//chrome/common/spellcheck_messages.h", + "//chrome/common/spellcheck_result.h", + "//chrome/renderer/spellchecker/custom_dictionary_engine.cc", + "//chrome/renderer/spellchecker/custom_dictionary_engine.h", + "//chrome/renderer/spellchecker/hunspell_engine.cc", + "//chrome/renderer/spellchecker/hunspell_engine.h", + "//chrome/renderer/spellchecker/spellcheck.cc", + "//chrome/renderer/spellchecker/spellcheck.h", + "//chrome/renderer/spellchecker/spellcheck_language.cc", + "//chrome/renderer/spellchecker/spellcheck_language.h", + "//chrome/renderer/spellchecker/spellcheck_provider.cc", + "//chrome/renderer/spellchecker/spellcheck_provider.h", + "//chrome/renderer/spellchecker/spellcheck_worditerator.cc", + "//chrome/renderer/spellchecker/spellcheck_worditerator.h", + "//chrome/renderer/spellchecker/spelling_engine.h", + ] + include_dirs += [ + "//third_party/WebKit" + ] + deps += [ + "//third_party/icu", + "//third_party/hunspell", + "//chrome/tools/convert_dict" + ] + + if (is_mac && use_browser_spellchecker) { + sources += [ + "//chrome/browser/spellchecker/spellcheck_message_filter_platform.h", + "//chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc", + ] + } + } + + 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 80337446f..280a0475d 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -669,6 +669,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; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 373dc7a5a..0355290d0 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); @@ -488,6 +500,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 @@ -502,21 +520,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(); } @@ -563,15 +615,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(); } @@ -959,19 +1013,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; diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 5b2f9a942..0accd3be5 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..3112e4484 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -347,6 +347,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_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/src.pro b/src/src.pro index 9b5373181..7f8b39cd6 100644 --- a/src/src.pro +++ b/src/src.pro @@ -13,8 +13,8 @@ SUBDIRS += core \ 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 +27,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 715081b5f..7bece36cd 100644 --- a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro +++ b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro @@ -1,12 +1,31 @@ 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.") } -# skip dummy main.cpp file -OBJECTS = +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 = +} # 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 871428f33..162dbe1d7 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..2cd4fadf1 --- /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) + 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) + + +public: + enum InjectionPoint { + Deferred, + DocumentReady, + DocumentCreation + }; + Q_ENUM(InjectionPoint) + + enum ScriptWorldId { + MainWorld = 0, + ApplicationWorld, + UserWorld + }; + Q_ENUM(ScriptWorldId) + + 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 c9eb9d342..8a3c6c24f 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -347,6 +347,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 @@ -540,6 +555,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..cb24a9c0b 100644 --- a/src/webengine/api/qquickwebenginetestsupport_p.h +++ b/src/webengine/api/qquickwebenginetestsupport_p.h @@ -75,7 +75,7 @@ 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(); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 4cef45f8c..2db25584c 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: @@ -1101,6 +1103,12 @@ 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 @@ -1318,7 +1326,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 b777a0898..582f0308c 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 QWebEngineDownloadItem::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 16e9438c9..2af3db414 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 @@ -1684,6 +1703,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); @@ -1936,17 +1967,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())); @@ -1955,7 +1994,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); @@ -1979,7 +2018,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())); @@ -1989,7 +2028,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) @@ -1998,6 +2037,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) @@ -2016,6 +2056,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())); @@ -2026,6 +2067,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) @@ -2033,7 +2075,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..bc5799aac 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; @@ -69,13 +73,13 @@ class QWebEngineSettings; class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject { Q_OBJECT - Q_PROPERTY(QString selectedText READ selectedText) - Q_PROPERTY(bool hasSelection READ hasSelection) + Q_PROPERTY(QString selectedText READ selectedText CONSTANT) + Q_PROPERTY(bool hasSelection READ hasSelection CONSTANT) // Ex-QWebFrame properties - Q_PROPERTY(QUrl requestedUrl READ requestedUrl) + Q_PROPERTY(QUrl requestedUrl READ requestedUrl CONSTANT) Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) - Q_PROPERTY(QString title READ title) + Q_PROPERTY(QString title READ title CONSTANT) Q_PROPERTY(QUrl url READ url WRITE setUrl) Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged) Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) @@ -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 8b4053e73..58d805fcb 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..ef3bf1f00 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; @@ -56,12 +57,12 @@ class QWebEngineViewPrivate; class QWEBENGINEWIDGETS_EXPORT QWebEngineView : public QWidget { Q_OBJECT - Q_PROPERTY(QString title READ title) + Q_PROPERTY(QString title READ title CONSTANT) Q_PROPERTY(QUrl url READ url WRITE setUrl) Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged) Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) - Q_PROPERTY(QString selectedText READ selectedText) - Q_PROPERTY(bool hasSelection READ hasSelection) + Q_PROPERTY(QString selectedText READ selectedText CONSTANT) + Q_PROPERTY(bool hasSelection READ hasSelection CONSTANT) Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor) public: @@ -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 07afd6501..1919d6ea7 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -160,6 +160,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/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/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/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..dcc2c4f5e 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(); @@ -499,15 +501,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 +524,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() @@ -704,5 +717,28 @@ void tst_QQuickWebEngineView::changeLocale() delete viewEN; } +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")); + + list.clear(); +} + QTEST_MAIN(tst_QQuickWebEngineView) #include "tst_qquickwebengineview.moc" 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..7e78e2b0e 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -4690,10 +4690,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 +4706,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); diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 151b82b61..b173c3474 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) \ @@ -90,6 +93,7 @@ private Q_SLOTS: void inputMethodsTextFormat(); void keyboardEvents(); void keyboardFocusAfterPopup(); + void postData(); void softwareInputPanel(); void hiddenText(); @@ -1089,6 +1093,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..759638877 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -23,8 +23,12 @@ 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(appstore-compliant): WEBENGINE_CONFIG += use_appstore_compliant_code } linux { @@ -85,9 +89,6 @@ defineTest(runConfigure) { 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)) diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf index 52bb5ec00..f3c2eb905 100644 --- a/tools/qmake/mkspecs/features/functions.prf +++ b/tools/qmake/mkspecs/features/functions.prf @@ -373,24 +373,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(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!") + } + } +} + +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)) + + win32: out = $${out}.exe + return($$out) +} - # If we did not find ninja, then we bootstrap it. +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)) - 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") + 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!") + } } - } - return($$system_path($$out)) } 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..ccc2831ae --- /dev/null +++ b/tools/qmake/mkspecs/features/gn_generator.prf @@ -0,0 +1,228 @@ +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_FRAMEWORKPATH) { + GN_CONTENTS += " mac_framework_dirs = [" + for(path, QMAKE_FRAMEWORKPATH): GN_CONTENTS += " \"$$path\"," + GN_CONTENTS += " ]" +} + +!isEmpty(QMAKE_CFLAGS) { + GN_CONTENTS += " cflags = [" + for(flag, QMAKE_CFLAGS): GN_CONTENTS += " \"$$filter_flag_values($$flag)\"," + 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. +for (define, DEFINES): GN_CONTENTS += " \"$$replace(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) { + macos: GN_CONTENTS += " \"-Wl,-rpath,$${QMAKE_RPATHDIR}\"," + else:unix: GN_CONTENTS += " \"-Wl,-rpath=$${QMAKE_RPATHDIR}\"," +} +!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: 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/take_snapshot.py b/tools/scripts/take_snapshot.py index 93575d821..78b8066ca 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 @@ -120,7 +120,6 @@ def isInChromiumBlacklist(file_path): 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/') @@ -159,7 +158,13 @@ def isInChromiumBlacklist(file_path): or (file_path.startswith('third_party/cacheinvalidation') and not file_path.endswith('isolate')) or file_path.startswith('third_party/boringssl/src/fuzz') - or file_path.startswith('third_party/catapult') + or (file_path.startswith('third_party/catapult') and not + (file_path.startswith('third_party/catapult/third_party/py_vulcanize') + or file_path.startswith('third_party/catapult/tracing/tracing/') + or file_path.startswith('third_party/catapult/tracing/tracing_build') + or file_path.startswith('third_party/catapult/tracing/third_party') + or file_path.startswith('third_party/catapult/tracing/bin') + or file_path.endswith('tracing_project.py'))) or file_path.startswith('third_party/chromite') or file_path.startswith('third_party/cld_2') or file_path.startswith('third_party/codesighs') |