diff options
Diffstat (limited to 'src/core')
188 files changed, 7749 insertions, 4660 deletions
diff --git a/src/core/accessibility_tree_formatter_qt.cpp b/src/core/accessibility_tree_formatter_qt.cpp new file mode 100644 index 000000000..8b15c5dee --- /dev/null +++ b/src/core/accessibility_tree_formatter_qt.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "content/browser/accessibility/accessibility_tree_formatter_browser.h" + +#include <utility> + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" + +#include "browser_accessibility_qt.h" + +namespace content { + +#ifndef QT_NO_ACCESSIBILITY +class AccessibilityTreeFormatterQt : public AccessibilityTreeFormatterBrowser { +public: + explicit AccessibilityTreeFormatterQt(); + ~AccessibilityTreeFormatterQt() override; + +private: + const base::FilePath::StringType GetExpectedFileSuffix() override; + const std::string GetAllowEmptyString() override; + const std::string GetAllowString() override; + const std::string GetDenyString() override; + void AddProperties(const BrowserAccessibility &node, base::DictionaryValue* dict) override; + base::string16 ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue * = nullptr) override; +}; + +AccessibilityTreeFormatterQt::AccessibilityTreeFormatterQt() +{ +} + +AccessibilityTreeFormatterQt::~AccessibilityTreeFormatterQt() +{ +} + +void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &node, base::DictionaryValue *dict) +{ + dict->SetInteger("id", node.GetId()); + const BrowserAccessibilityQt *acc_node = ToBrowserAccessibilityQt(&node); + + dict->SetString("role", qAccessibleRoleString(acc_node->role())); + + QAccessible::State state = acc_node->state(); + + std::vector<base::Value> states; + if (state.busy) + states.push_back(base::Value("busy")); + if (state.checkable) + states.push_back(base::Value("checkable")); + if (state.checked) + states.push_back(base::Value("checked")); + if (acc_node->IsClickable()) + states.push_back(base::Value("clickable")); + if (state.collapsed) + states.push_back(base::Value("collapsed")); + if (state.disabled) + states.push_back(base::Value("disabled")); + if (state.editable) + states.push_back(base::Value("editable")); + if (state.expandable) + states.push_back(base::Value("expandable")); + if (state.expanded) + states.push_back(base::Value("expanded")); + if (state.focusable) + states.push_back(base::Value("focusable")); + if (state.focused) + states.push_back(base::Value("focused")); + if (state.hasPopup) + states.push_back(base::Value("hasPopup")); + if (state.hotTracked) + states.push_back(base::Value("hotTracked")); + if (state.invisible) + states.push_back(base::Value("invisible")); + if (state.linked) + states.push_back(base::Value("linked")); + if (state.multiLine) + states.push_back(base::Value("multiLine")); + if (state.multiSelectable) + states.push_back(base::Value("multiSelectable")); + if (state.modal) + states.push_back(base::Value("modal")); + if (state.offscreen) + states.push_back(base::Value("offscreen")); + if (state.passwordEdit) + states.push_back(base::Value("password")); + if (state.pressed) + states.push_back(base::Value("pressed")); + if (state.readOnly) + states.push_back(base::Value("readOnly")); + if (state.selectable) + states.push_back(base::Value("selectable")); + if (state.selected) + states.push_back(base::Value("selected")); + if (state.traversed) + states.push_back(base::Value("traversed")); + dict->SetKey("states", base::Value(states)); + + dict->SetString("name", acc_node->text(QAccessible::Name).toStdString()); + dict->SetString("description", acc_node->text(QAccessible::Description).toStdString()); +} + +base::string16 AccessibilityTreeFormatterQt::ProcessTreeForOutput(const base::DictionaryValue &node, base::DictionaryValue *) +{ + base::string16 error_value; + if (node.GetString("error", &error_value)) + return error_value; + + base::string16 line; + std::string role_value; + node.GetString("role", &role_value); + if (!role_value.empty()) + WriteAttribute(true, base::StringPrintf("%s", role_value.c_str()), &line); + + const base::ListValue *states_value = nullptr; + node.GetList("states", &states_value); + if (states_value) { + for (const auto &state : *states_value) { + std::string state_value; + if (state.GetAsString(&state_value)) + WriteAttribute(true, state_value, &line); + } + } + + std::string name_value; + if (node.GetString("name", &name_value)) + WriteAttribute(true, base::StringPrintf("name='%s'", name_value.c_str()), &line); + + std::string description_value; + if (node.GetString("description", &description_value)) + WriteAttribute(false, base::StringPrintf("description='%s'", description_value.c_str()), &line); + + int id_value; + node.GetInteger("id", &id_value); + WriteAttribute(false, base::StringPrintf("id=%d", id_value), &line); + + return line + base::ASCIIToUTF16("\n"); +} + +const base::FilePath::StringType AccessibilityTreeFormatterQt::GetExpectedFileSuffix() +{ + return FILE_PATH_LITERAL("-expected-qt.txt"); +} + +const std::string AccessibilityTreeFormatterQt::GetAllowEmptyString() +{ + return "@QT-ALLOW-EMPTY:"; +} + +const std::string AccessibilityTreeFormatterQt::GetAllowString() +{ + return "@QT-ALLOW:"; +} + +const std::string AccessibilityTreeFormatterQt::GetDenyString() +{ + return "@QT-DENY:"; +} + +#endif // QT_NO_ACCESSIBILITY + +// static +AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create() +{ +#ifndef QT_NO_ACCESSIBILITY + return new AccessibilityTreeFormatterQt(); +#else + return nullptr; +#endif +} + +} // namespace content diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 632034a9d..38dc6b39d 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -3,9 +3,8 @@ DESTDIR = $$OUT_PWD/$$getConfigDir() TEMPLATE = lib -CONFIG += staticlib c++14 -QT += network core-private -QT_PRIVATE += webenginecoreheaders-private +CONFIG += staticlib +QT += network core-private webenginecoreheaders-private # Don't create .prl file for this intermediate library because # their contents get used when linking against them, breaking @@ -23,17 +22,18 @@ DEFINES += \ NOMINMAX CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() +CHROMIUM_GEN_DIR = $$OUT_PWD/../$$getConfigDir()/gen INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core \ + $$CHROMIUM_GEN_DIR \ $$CHROMIUM_SRC_DIR -linux-g++*: QMAKE_CXXFLAGS += -Wno-unused-parameter +gcc: QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter HEADERS = \ qwebenginecallback.h \ qwebenginecallback_p.h \ qtwebenginecoreglobal.h \ qtwebenginecoreglobal_p.h \ - qwebenginebrowsercontext_p.h \ qwebenginecookiestore.h \ qwebenginecookiestore_p.h \ qwebenginehttprequest.h \ @@ -43,21 +43,23 @@ HEADERS = \ qwebengineurlrequestinfo.h \ qwebengineurlrequestinfo_p.h \ qwebengineurlrequestjob.h \ + qwebengineurlscheme.h \ qwebengineurlschemehandler.h SOURCES = \ qtwebenginecoreglobal.cpp \ - qwebenginebrowsercontext.cpp \ qwebenginecookiestore.cpp \ qwebenginehttprequest.cpp \ qwebenginequotarequest.cpp \ qwebengineregisterprotocolhandlerrequest.cpp \ qwebengineurlrequestinfo.cpp \ qwebengineurlrequestjob.cpp \ + qwebengineurlscheme.cpp \ qwebengineurlschemehandler.cpp ### Qt6 Remove this workaround unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!static { + CONFIG -= warning_clean SOURCES += qtbug-60565.cpp \ qtbug-61521.cpp } @@ -69,3 +71,5 @@ msvc { "if exist $(DESTDIR_TARGET).objects del $(DESTDIR_TARGET).objects$$escape_expand(\\n\\t)" \ "for %%a in ($(OBJECTS)) do echo $$shell_quote($$shell_path($$OUT_PWD))\\%%a >> $(DESTDIR_TARGET).objects" } + +load(qt_common) diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 4bb69ac21..a415ade92 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -89,7 +89,7 @@ static void deleteShareContext() // after the QGuiApplication creation, when AA_ShareOpenGLContexts fills // the same need but the flag has to be set earlier. -QWEBENGINE_PRIVATE_EXPORT void initialize() +QWEBENGINECORE_PRIVATE_EXPORT void initialize() { #ifndef QT_NO_OPENGL #ifdef Q_OS_WIN32 diff --git a/src/core/api/qtwebenginecoreglobal.h b/src/core/api/qtwebenginecoreglobal.h index 012c5d4f0..bcff622b7 100644 --- a/src/core/api/qtwebenginecoreglobal.h +++ b/src/core/api/qtwebenginecoreglobal.h @@ -41,13 +41,14 @@ #define QTWEBENGINECOREGLOBAL_H #include <QtCore/qglobal.h> +#include <QtWebEngineCore/qtwebenginecore-config.h> QT_BEGIN_NAMESPACE #if defined(BUILDING_CHROMIUM) -# define QWEBENGINE_EXPORT Q_DECL_EXPORT +# define QWEBENGINECORE_EXPORT Q_DECL_EXPORT #else -# define QWEBENGINE_EXPORT Q_DECL_IMPORT +# define QWEBENGINECORE_EXPORT Q_DECL_IMPORT #endif #define ASSERT_ENUMS_MATCH(A, B) Q_STATIC_ASSERT_X(static_cast<int>(A) == static_cast<int>(B), "The enum values must match"); diff --git a/src/core/api/qtwebenginecoreglobal_p.h b/src/core/api/qtwebenginecoreglobal_p.h index 0a6ae3f91..27bf2d9f9 100644 --- a/src/core/api/qtwebenginecoreglobal_p.h +++ b/src/core/api/qtwebenginecoreglobal_p.h @@ -51,7 +51,9 @@ // We mean it. // -#include "qtwebenginecoreglobal.h" +#include <QtWebEngineCore/qtwebenginecoreglobal.h> +#include <QtCore/private/qglobal_p.h> +#include <QtWebEngineCore/private/qtwebenginecore-config_p.h> #ifdef QT_WEBENGINE_LOGGING #define QT_NOT_YET_IMPLEMENTED fprintf(stderr, "function %s not implemented! - %s:%d\n", __func__, __FILE__, __LINE__); @@ -61,6 +63,6 @@ #define QT_NOT_USED Q_UNREACHABLE(); // This will assert in debug. #endif -#define QWEBENGINE_PRIVATE_EXPORT QWEBENGINE_EXPORT +#define QWEBENGINECORE_PRIVATE_EXPORT QWEBENGINECORE_EXPORT #endif // QTWEBENGINECOREGLOBAL_P_H diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp index fa72265dc..035c98342 100644 --- a/src/core/api/qwebenginecookiestore.cpp +++ b/src/core/api/qwebenginecookiestore.cpp @@ -94,7 +94,7 @@ void QWebEngineCookieStorePrivate::processPendingUserCookies() if (m_pendingUserCookies.isEmpty()) return; - Q_FOREACH (const auto &cookieData, m_pendingUserCookies) { + for (const CookieData &cookieData : qAsConst(m_pendingUserCookies)) { if (cookieData.callbackId == CallbackDirectory::DeleteCookieCallbackId) delegate->deleteCookie(cookieData.cookie, cookieData.origin); else @@ -184,14 +184,13 @@ void QWebEngineCookieStorePrivate::onDeleteCallbackResult(qint64 callbackId, int void QWebEngineCookieStorePrivate::onCookieChanged(const QNetworkCookie &cookie, bool removed) { - Q_Q(QWebEngineCookieStore); if (removed) - Q_EMIT q->cookieRemoved(cookie); + Q_EMIT q_ptr->cookieRemoved(cookie); else - Q_EMIT q->cookieAdded(cookie); + Q_EMIT q_ptr->cookieAdded(cookie); } -bool QWebEngineCookieStorePrivate::canAccessCookies(const QUrl &firstPartyUrl, const QUrl &url) +bool QWebEngineCookieStorePrivate::canAccessCookies(const QUrl &firstPartyUrl, const QUrl &url) const { if (!filterCallback) return true; @@ -269,8 +268,7 @@ QWebEngineCookieStore::~QWebEngineCookieStore() void QWebEngineCookieStore::setCookie(const QNetworkCookie &cookie, const QUrl &origin) { //TODO: use callbacks or delete dummy ones - Q_D(QWebEngineCookieStore); - d->setCookie(QWebEngineCallback<bool>(), cookie, origin); + d_ptr->setCookie(QWebEngineCallback<bool>(), cookie, origin); } /*! @@ -283,8 +281,7 @@ void QWebEngineCookieStore::setCookie(const QNetworkCookie &cookie, const QUrl & void QWebEngineCookieStore::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) { - Q_D(QWebEngineCookieStore); - d->deleteCookie(cookie, origin); + d_ptr->deleteCookie(cookie, origin); } /*! @@ -299,12 +296,11 @@ void QWebEngineCookieStore::deleteCookie(const QNetworkCookie &cookie, const QUr void QWebEngineCookieStore::loadAllCookies() { //TODO: use callbacks or delete dummy ones - Q_D(QWebEngineCookieStore); - if (d->m_getAllCookiesPending) + if (d_ptr->m_getAllCookiesPending) return; - d->callbackDirectory.registerCallback(CallbackDirectory::GetAllCookiesCallbackId, QWebEngineCallback<const QByteArray&>()); + d_ptr->callbackDirectory.registerCallback(CallbackDirectory::GetAllCookiesCallbackId, QWebEngineCallback<const QByteArray&>()); //this will trigger cookieAdded signal - d->getAllCookies(); + d_ptr->getAllCookies(); } /*! @@ -318,11 +314,10 @@ void QWebEngineCookieStore::loadAllCookies() void QWebEngineCookieStore::deleteSessionCookies() { //TODO: use callbacks or delete dummy ones - Q_D(QWebEngineCookieStore); - if (d->m_deleteAllCookiesPending || d->m_deleteSessionCookiesPending) + if (d_ptr->m_deleteAllCookiesPending || d_ptr->m_deleteSessionCookiesPending) return; - d->callbackDirectory.registerCallback(CallbackDirectory::DeleteSessionCookiesCallbackId, QWebEngineCallback<int>()); - d->deleteSessionCookies(); + d_ptr->callbackDirectory.registerCallback(CallbackDirectory::DeleteSessionCookiesCallbackId, QWebEngineCallback<int>()); + d_ptr->deleteSessionCookies(); } /*! @@ -334,11 +329,10 @@ void QWebEngineCookieStore::deleteSessionCookies() void QWebEngineCookieStore::deleteAllCookies() { //TODO: use callbacks or delete dummy ones - Q_D(QWebEngineCookieStore); - if (d->m_deleteAllCookiesPending) + if (d_ptr->m_deleteAllCookiesPending) return; - d->callbackDirectory.registerCallback(CallbackDirectory::DeleteAllCookiesCallbackId, QWebEngineCallback<int>()); - d->deleteAllCookies(); + d_ptr->callbackDirectory.registerCallback(CallbackDirectory::DeleteAllCookiesCallbackId, QWebEngineCallback<int>()); + d_ptr->deleteAllCookies(); } /*! @@ -371,8 +365,7 @@ void QWebEngineCookieStore::deleteAllCookies() */ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const FilterRequest &)> &filterCallback) { - Q_D(QWebEngineCookieStore); - d->filterCallback = filterCallback; + d_ptr->filterCallback = filterCallback; } /*! @@ -381,8 +374,7 @@ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const Filte */ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterRequest &)> &&filterCallback) { - Q_D(QWebEngineCookieStore); - d->filterCallback = std::move(filterCallback); + d_ptr->filterCallback = std::move(filterCallback); } /*! diff --git a/src/core/api/qwebenginecookiestore.h b/src/core/api/qwebenginecookiestore.h index 87d7390a3..89e72dfb0 100644 --- a/src/core/api/qwebenginecookiestore.h +++ b/src/core/api/qwebenginecookiestore.h @@ -50,14 +50,14 @@ #include <functional> namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class CookieMonsterDelegateQt; } QT_BEGIN_NAMESPACE class QWebEngineCookieStorePrivate; -class QWEBENGINE_EXPORT QWebEngineCookieStore : public QObject { +class QWEBENGINECORE_EXPORT QWebEngineCookieStore : public QObject { Q_OBJECT public: @@ -84,7 +84,7 @@ Q_SIGNALS: private: explicit QWebEngineCookieStore(QObject *parent = Q_NULLPTR); - friend class QtWebEngineCore::BrowserContextAdapter; + friend class QtWebEngineCore::ProfileAdapter; friend class QtWebEngineCore::CookieMonsterDelegateQt; Q_DISABLE_COPY(QWebEngineCookieStore) Q_DECLARE_PRIVATE(QWebEngineCookieStore) diff --git a/src/core/api/qwebenginecookiestore_p.h b/src/core/api/qwebenginecookiestore_p.h index e44a80f53..93198d8ed 100644 --- a/src/core/api/qwebenginecookiestore_p.h +++ b/src/core/api/qwebenginecookiestore_p.h @@ -66,7 +66,7 @@ class CookieMonsterDelegateQt; QT_BEGIN_NAMESPACE -class QWEBENGINE_PRIVATE_EXPORT QWebEngineCookieStorePrivate +class QWEBENGINECORE_PRIVATE_EXPORT QWebEngineCookieStorePrivate { Q_DECLARE_PUBLIC(QWebEngineCookieStore) struct CookieData { @@ -97,7 +97,7 @@ public: void deleteAllCookies(); void getAllCookies(); - bool canAccessCookies(const QUrl &firstPartyUrl, const QUrl &url); + bool canAccessCookies(const QUrl &firstPartyUrl, const QUrl &url) const; void onGetAllCallbackResult(qint64 callbackId, const QByteArray &cookieList); void onSetCallbackResult(qint64 callbackId, bool success); diff --git a/src/core/api/qwebenginehttprequest.h b/src/core/api/qwebenginehttprequest.h index 5b5948ba1..c6b5a6b63 100644 --- a/src/core/api/qwebenginehttprequest.h +++ b/src/core/api/qwebenginehttprequest.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QWebEngineHttpRequestPrivate; -class QWEBENGINE_EXPORT QWebEngineHttpRequest +class QWEBENGINECORE_EXPORT QWebEngineHttpRequest { public: enum Method { diff --git a/src/core/api/qwebenginequotarequest.h b/src/core/api/qwebenginequotarequest.h index be71635c1..a759f5bb6 100644 --- a/src/core/api/qwebenginequotarequest.h +++ b/src/core/api/qwebenginequotarequest.h @@ -51,7 +51,7 @@ class QuotaRequestController; QT_BEGIN_NAMESPACE -class QWEBENGINE_EXPORT QWebEngineQuotaRequest { +class QWEBENGINECORE_EXPORT QWebEngineQuotaRequest { Q_GADGET Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL) Q_PROPERTY(qint64 requestedSize READ requestedSize CONSTANT FINAL) diff --git a/src/core/api/qwebengineregisterprotocolhandlerrequest.h b/src/core/api/qwebengineregisterprotocolhandlerrequest.h index b3707bc59..12b1d6edf 100644 --- a/src/core/api/qwebengineregisterprotocolhandlerrequest.h +++ b/src/core/api/qwebengineregisterprotocolhandlerrequest.h @@ -51,7 +51,7 @@ class WebContentsDelegateQt; QT_BEGIN_NAMESPACE -class QWEBENGINE_EXPORT QWebEngineRegisterProtocolHandlerRequest { +class QWEBENGINECORE_EXPORT QWebEngineRegisterProtocolHandlerRequest { Q_GADGET Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL) Q_PROPERTY(QString scheme READ scheme CONSTANT FINAL) diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index e6972932e..2bb870071 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -192,8 +192,7 @@ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPriva QWebEngineUrlRequestInfo::ResourceType QWebEngineUrlRequestInfo::resourceType() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->resourceType; + return d_ptr->resourceType; } /*! @@ -217,8 +216,7 @@ QWebEngineUrlRequestInfo::ResourceType QWebEngineUrlRequestInfo::resourceType() QWebEngineUrlRequestInfo::NavigationType QWebEngineUrlRequestInfo::navigationType() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->navigationType; + return d_ptr->navigationType; } /*! @@ -227,8 +225,7 @@ QWebEngineUrlRequestInfo::NavigationType QWebEngineUrlRequestInfo::navigationTyp QUrl QWebEngineUrlRequestInfo::requestUrl() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->url; + return d_ptr->url; } /*! @@ -238,8 +235,7 @@ QUrl QWebEngineUrlRequestInfo::requestUrl() const QUrl QWebEngineUrlRequestInfo::firstPartyUrl() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->firstPartyUrl; + return d_ptr->firstPartyUrl; } @@ -249,8 +245,7 @@ QUrl QWebEngineUrlRequestInfo::firstPartyUrl() const QByteArray QWebEngineUrlRequestInfo::requestMethod() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->method; + return d_ptr->method; } /*! @@ -258,8 +253,7 @@ QByteArray QWebEngineUrlRequestInfo::requestMethod() const */ bool QWebEngineUrlRequestInfo::changed() const { - Q_D(const QWebEngineUrlRequestInfo); - return d->changed; + return d_ptr->changed; } /*! @@ -269,9 +263,8 @@ bool QWebEngineUrlRequestInfo::changed() const void QWebEngineUrlRequestInfo::redirect(const QUrl &url) { - Q_D(QWebEngineUrlRequestInfo); - d->changed = true; - d->url = url; + d_ptr->changed = true; + d_ptr->url = url; } /*! @@ -282,9 +275,8 @@ void QWebEngineUrlRequestInfo::redirect(const QUrl &url) void QWebEngineUrlRequestInfo::block(bool shouldBlock) { - Q_D(QWebEngineUrlRequestInfo); - d->changed = true; - d->shouldBlockRequest = shouldBlock; + d_ptr->changed = true; + d_ptr->shouldBlockRequest = shouldBlock; } /*! @@ -293,9 +285,8 @@ void QWebEngineUrlRequestInfo::block(bool shouldBlock) void QWebEngineUrlRequestInfo::setHttpHeader(const QByteArray &name, const QByteArray &value) { - Q_D(QWebEngineUrlRequestInfo); - d->changed = true; - d->extraHeaders.insert(name, value); + d_ptr->changed = true; + d_ptr->extraHeaders.insert(name, value); } QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h index 52463a1b3..68c46dcf4 100644 --- a/src/core/api/qwebengineurlrequestinfo.h +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE class QWebEngineUrlRequestInfoPrivate; -class QWEBENGINE_EXPORT QWebEngineUrlRequestInfo { +class QWEBENGINECORE_EXPORT QWebEngineUrlRequestInfo { public: enum ResourceType { ResourceTypeMainFrame = 0, // top level page diff --git a/src/core/api/qwebengineurlrequestinterceptor.h b/src/core/api/qwebengineurlrequestinterceptor.h index 6e0f93e49..dc2a15ee3 100644 --- a/src/core/api/qwebengineurlrequestinterceptor.h +++ b/src/core/api/qwebengineurlrequestinterceptor.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE -class QWEBENGINE_EXPORT QWebEngineUrlRequestInterceptor : public QObject +class QWEBENGINECORE_EXPORT QWebEngineUrlRequestInterceptor : public QObject { Q_OBJECT Q_DISABLE_COPY(QWebEngineUrlRequestInterceptor) diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h index 7a7dbd83d..7ce8be7ec 100644 --- a/src/core/api/qwebengineurlrequestjob.h +++ b/src/core/api/qwebengineurlrequestjob.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE class QIODevice; -class QWEBENGINE_EXPORT QWebEngineUrlRequestJob : public QObject { +class QWEBENGINECORE_EXPORT QWebEngineUrlRequestJob : public QObject { Q_OBJECT public: ~QWebEngineUrlRequestJob(); diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp new file mode 100644 index 000000000..f36f3335b --- /dev/null +++ b/src/core/api/qwebengineurlscheme.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "qwebengineurlscheme.h" + +#include <url/url_util_qt.h> + +QT_BEGIN_NAMESPACE + +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::Path, url::SCHEME_WITHOUT_AUTHORITY) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::Host, url::SCHEME_WITH_HOST) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::HostAndPort, url::SCHEME_WITH_HOST_AND_PORT) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::Syntax::HostPortAndUserInformation, + url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION) + +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::PortUnspecified, url::PORT_UNSPECIFIED) + +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::SecureScheme, url::CustomScheme::Secure) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::LocalScheme, url::CustomScheme::Local) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::LocalAccessAllowed, url::CustomScheme::LocalAccessAllowed) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::NoAccessAllowed, url::CustomScheme::NoAccessAllowed) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ServiceWorkersAllowed, url::CustomScheme::ServiceWorkersAllowed) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ViewSourceAllowed, url::CustomScheme::ViewSourceAllowed) +ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ContentSecurityPolicyIgnored, url::CustomScheme::ContentSecurityPolicyIgnored) + +class QWebEngineUrlSchemePrivate : public QSharedData + , public url::CustomScheme +{ +public: + QWebEngineUrlSchemePrivate() {} + QWebEngineUrlSchemePrivate(const url::CustomScheme &cs) : url::CustomScheme(cs) {} + static QSharedDataPointer<QWebEngineUrlSchemePrivate> defaultConstructed() + { + static QSharedDataPointer<QWebEngineUrlSchemePrivate> instance(new QWebEngineUrlSchemePrivate); + return instance; + } +}; + +/*! + \class QWebEngineUrlScheme + \inmodule QtWebEngineCore + \since 5.12 + \brief The QWebEngineUrlScheme class configures a custom URL scheme. + + A web engine URL scheme describes a URL scheme from the web engine's + perspective, specifying how URLs of this scheme should be parsed, and which + security restrictions should be placed on resources originating from such + URLs. + + Custom URL schemes must be configured early at application startup, before + creating any Qt WebEngine classes. The configuration applies globally to all + profiles. + + \code + int main(int argc, char **argv) + { + QWebEngineUrlScheme scheme("myscheme"); + scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort); + scheme.setDefaultPort(2345); + scheme.setFlags(QWebEngineUrlScheme::SecureScheme); + QWebEngineUrlScheme::registerScheme(scheme); + ... + } + \endcode + + To actually make use of the custom URL scheme, a \l QWebEngineUrlSchemeHandler + must be created and registered in a profile. + + \sa QWebEngineUrlSchemeHandler +*/ + +/*! + \enum QWebEngineUrlScheme::Syntax + + This enum type lists types of URL syntax. + + To apply the same-origin policy to a custom URL scheme, WebEngine must be able + to compute the origin (host and port combination) of a URL. The \c {Host...} + options indicate that the URL scheme conforms to the standard URL syntax (like + \c http) and automatically enable the same-origin policy. The \c {Path} + option indicates that the URL scheme uses a non-standard syntax and that the + same-origin policy cannot be applied. + + \value HostPortAndUserInformation + The authority component of a URL of this type has all of the standard + elements: host, port, user name, and password. A URL without a port will use + the \l defaultPort (which \e must not be \l PortUnspecified). + + \value HostAndPort + The authority component of a URL of this type has only the host and port + elements. A URL without a port will use the \l defaultPort (which \e must not + be \l PortUnspecified). + + \value Host + The authority component of a URL of this type has only the host part and no + port. The \l defaultPort \e must be set to \l PortUnspecified. + + \value Path + A URL of this type has no authority component at all. Everything after scheme + name and separator character (:) will be preserved as is without validation + or canonicalization. All URLs of such a scheme will be considered as having + the same origin (unless the \c NoAccessAllowed flag is used). +*/ + +/*! + \enum QWebEngineUrlScheme::SpecialPort + + This enum type defines special values for \l defaultPort. + + \value PortUnspecified + Indicates that the URL scheme does not have a port element. +*/ + +/*! + \enum QWebEngineUrlScheme::Flag + + This enum type specifies security options that should apply to a URL scheme. + + \value SecureScheme + Indicates that the URL scheme is + \l{https://www.w3.org/TR/powerful-features/#is-origin-trustworthy}{potentially + trustworthy}. This flag should only be applied to URL schemes which ensure + data authenticity, confidentiality, and integrity, either through encryption + or other means. Examples of secure builtin schemes include \c https + (authenticated and encrypted) and \c qrc (local resources only), whereas \c + http is an example of an insecure scheme. + + \value LocalScheme + Indicates that the URL scheme provides access to local resources. The purpose + of this flag is to prevent network content from accessing local resources. + Only schemes with the \c LocalAccessAllowed flag may load resources from a + scheme with the \c Local flag. The only builtin schemes with this flag are \c + file and \c qrc. + + \value LocalAccessAllowed + Indicates that content from this scheme should be allowed to load resources + from schemes with the \c Local flag. + + \value NoAccessAllowed + Indicates that all content from this scheme should be forced to have unique + opaque origins: no two resources will have the same origin. + + \value ServiceWorkersAllowed + Indicates that the Service Workers API should be enabled. + + \value ViewSourceAllowed + Indicates that the View Source feature should be enabled. + + \value ContentSecurityPolicyIgnored + Indicates that accesses to this scheme should bypass all + Content-Security-Policy checks. +*/ + +QWebEngineUrlScheme::QWebEngineUrlScheme(QWebEngineUrlSchemePrivate *d) + : d(d) +{ +} + +/*! + Constructs a web engine URL scheme with default values. +*/ +QWebEngineUrlScheme::QWebEngineUrlScheme() + : QWebEngineUrlScheme(QWebEngineUrlSchemePrivate::defaultConstructed()) +{ +} + +/*! + Constructs a web engine URL scheme with given \a name. +*/ +QWebEngineUrlScheme::QWebEngineUrlScheme(const QByteArray &name) + : QWebEngineUrlScheme() +{ + setName(name); +} + +/*! + Copies \a that. +*/ +QWebEngineUrlScheme::QWebEngineUrlScheme(const QWebEngineUrlScheme &that) = default; + +/*! + Copies \a that. +*/ +QWebEngineUrlScheme &QWebEngineUrlScheme::operator=(const QWebEngineUrlScheme &that) = default; + +/*! + Moves \a that. +*/ +QWebEngineUrlScheme::QWebEngineUrlScheme(QWebEngineUrlScheme &&that) = default; + +/*! + Moves \a that. +*/ +QWebEngineUrlScheme &QWebEngineUrlScheme::operator=(QWebEngineUrlScheme &&that) = default; + +/*! + Destructs this object. +*/ +QWebEngineUrlScheme::~QWebEngineUrlScheme() = default; + +/*! + Returns \c true if this and \a that object are equal. +*/ +bool QWebEngineUrlScheme::operator==(const QWebEngineUrlScheme &that) const +{ + return (d == that.d) + || (d->name == that.d->name + && d->type == that.d->type + && d->default_port == that.d->default_port + && d->flags == that.d->flags); +} + +/*! + \fn bool QWebEngineUrlScheme::operator!=(const QWebEngineUrlScheme &that) const + + Returns \c true if this and \a that object are not equal. +*/ + +/*! + Returns the name of this URL scheme. + + The default value is an empty string. + + \sa setName() +*/ +QByteArray QWebEngineUrlScheme::name() const +{ + return QByteArray::fromStdString(d->name); +} + +/*! + Sets the name of this URL scheme to \a newValue. + + \note The name is automatically converted to lower case. + + \sa name() +*/ +void QWebEngineUrlScheme::setName(const QByteArray &newValue) +{ + d->name = newValue.toLower().toStdString(); +} + +/*! + Returns the syntax type of this URL scheme. + + The default value is \c Path. + + \sa Syntax, setSyntax() +*/ +QWebEngineUrlScheme::Syntax QWebEngineUrlScheme::syntax() const +{ + return static_cast<Syntax>(d->type); +} + +/*! + Sets the syntax type of this URL scheme to \a newValue. + + \sa Syntax, syntax() +*/ +void QWebEngineUrlScheme::setSyntax(Syntax newValue) +{ + d->type = static_cast<url::SchemeType>(newValue); +} + +/*! + Returns the default port of this URL scheme. + + The default value is \c PortUnspecified. + + \sa setDefaultPort() +*/ +int QWebEngineUrlScheme::defaultPort() const +{ + return d->default_port; +} + +/*! + Sets the default port of this URL scheme to \a newValue. + + \sa defaultPort() +*/ +void QWebEngineUrlScheme::setDefaultPort(int newValue) +{ + d->default_port = newValue; +} + +/*! + Returns the flags for this URL scheme. + + The default value is an empty set of flags. + + \sa Flags, setFlags() +*/ +QWebEngineUrlScheme::Flags QWebEngineUrlScheme::flags() const +{ + return Flags(d->flags); +} + +/*! + Sets the flags for this URL scheme to \a newValue. + + \sa Flags, flags() +*/ +void QWebEngineUrlScheme::setFlags(Flags newValue) +{ + d->flags = newValue; +} + +/*! + Registers \a scheme with the web engine's URL parser and security model. + + It is recommended that all custom URL schemes are first registered with this + function at application startup, even if the default options are to be used. + + \warning This function must be called early at application startup, before + creating any WebEngine classes. Late calls will be ignored. + + \sa schemeByName() +*/ +void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme) +{ + url::CustomScheme::AddScheme(*scheme.d); +} + +/*! + Returns the web engine URL scheme with the given \a name or the + default-constructed scheme. + + \sa registerScheme() +*/ +QWebEngineUrlScheme QWebEngineUrlScheme::schemeByName(const QByteArray &name) +{ + base::StringPiece namePiece{name.data(), static_cast<size_t>(name.size())}; + if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(namePiece)) + return QWebEngineUrlScheme(new QWebEngineUrlSchemePrivate(*cs)); + return QWebEngineUrlScheme(); +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlscheme.h b/src/core/api/qwebengineurlscheme.h new file mode 100644 index 000000000..88a8f5065 --- /dev/null +++ b/src/core/api/qwebengineurlscheme.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 QWEBENGINEURLSCHEME_H +#define QWEBENGINEURLSCHEME_H + +#include <QtWebEngineCore/qtwebenginecoreglobal.h> + +#include <QtCore/qbytearray.h> +#include <QtCore/qobjectdefs.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QWebEngineUrlSchemePrivate; + +class QWEBENGINECORE_EXPORT QWebEngineUrlScheme { + Q_GADGET +public: + enum class Syntax { + HostPortAndUserInformation, + HostAndPort, + Host, + Path, + }; + + enum SpecialPort { + PortUnspecified = -1 + }; + + enum Flag { + SecureScheme = 0x1, + LocalScheme = 0x2, + LocalAccessAllowed = 0x4, + NoAccessAllowed = 0x8, + ServiceWorkersAllowed = 0x10, + ViewSourceAllowed = 0x20, + ContentSecurityPolicyIgnored = 0x40, + }; + Q_DECLARE_FLAGS(Flags, Flag) + Q_FLAG(Flags) + + QWebEngineUrlScheme(); + explicit QWebEngineUrlScheme(const QByteArray &name); + + QWebEngineUrlScheme(const QWebEngineUrlScheme &that); + QWebEngineUrlScheme &operator=(const QWebEngineUrlScheme &that); + + QWebEngineUrlScheme(QWebEngineUrlScheme &&that); + QWebEngineUrlScheme &operator=(QWebEngineUrlScheme &&that); + + ~QWebEngineUrlScheme(); + + bool operator==(const QWebEngineUrlScheme &that) const; + bool operator!=(const QWebEngineUrlScheme &that) const { return !(*this == that); } + + QByteArray name() const; + void setName(const QByteArray &newValue); + + Syntax syntax() const; + void setSyntax(Syntax newValue); + + int defaultPort() const; + void setDefaultPort(int newValue); + + Flags flags() const; + void setFlags(Flags newValue); + + static void registerScheme(const QWebEngineUrlScheme &scheme); + static QWebEngineUrlScheme schemeByName(const QByteArray &name); + +private: + QWebEngineUrlScheme(QWebEngineUrlSchemePrivate *d); + QSharedDataPointer<QWebEngineUrlSchemePrivate> d; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QWebEngineUrlScheme::Flags) + +QT_END_NAMESPACE + +#endif // !QWEBENGINEURLSCHEME_H diff --git a/src/core/api/qwebengineurlschemehandler.h b/src/core/api/qwebengineurlschemehandler.h index 757c461f4..23fee4b95 100644 --- a/src/core/api/qwebengineurlschemehandler.h +++ b/src/core/api/qwebengineurlschemehandler.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QWebEngineUrlRequestJob; -class QWEBENGINE_EXPORT QWebEngineUrlSchemeHandler : public QObject { +class QWEBENGINECORE_EXPORT QWebEngineUrlSchemeHandler : public QObject { Q_OBJECT public: QWebEngineUrlSchemeHandler(QObject *parent = Q_NULLPTR); diff --git a/src/core/authentication_dialog_controller.cpp b/src/core/authentication_dialog_controller.cpp index 2f70ea923..bd23d1768 100644 --- a/src/core/authentication_dialog_controller.cpp +++ b/src/core/authentication_dialog_controller.cpp @@ -44,7 +44,7 @@ namespace QtWebEngineCore { -AuthenticationDialogControllerPrivate::AuthenticationDialogControllerPrivate(ResourceDispatcherHostLoginDelegateQt *loginDelegate) +AuthenticationDialogControllerPrivate::AuthenticationDialogControllerPrivate(LoginDelegateQt *loginDelegate) : loginDelegate(loginDelegate) { } @@ -53,7 +53,7 @@ void AuthenticationDialogControllerPrivate::dialogFinished(bool accepted, const { content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester, loginDelegate, accepted, user, password)); + base::Bind(&LoginDelegateQt::sendAuthToRequester, loginDelegate, accepted, user, password)); } AuthenticationDialogController::AuthenticationDialogController(AuthenticationDialogControllerPrivate *dd) diff --git a/src/core/authentication_dialog_controller.h b/src/core/authentication_dialog_controller.h index 2fa4e854f..aec91aac5 100644 --- a/src/core/authentication_dialog_controller.h +++ b/src/core/authentication_dialog_controller.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef AUTHENTICATION_DIALOG_CONTROLLER_H #define AUTHENTICATION_DIALOG_CONTROLLER_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QObject> @@ -48,7 +59,7 @@ namespace QtWebEngineCore { class AuthenticationDialogControllerPrivate; -class QWEBENGINE_EXPORT AuthenticationDialogController : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT AuthenticationDialogController : public QObject { Q_OBJECT public: ~AuthenticationDialogController(); @@ -66,7 +77,7 @@ private: AuthenticationDialogController(AuthenticationDialogControllerPrivate *); QScopedPointer<AuthenticationDialogControllerPrivate> d; - friend class ResourceDispatcherHostLoginDelegateQt; + friend class LoginDelegateQt; }; } // namespace QtWebEngineCore diff --git a/src/core/authentication_dialog_controller_p.h b/src/core/authentication_dialog_controller_p.h index af5d92530..16069b9b1 100644 --- a/src/core/authentication_dialog_controller_p.h +++ b/src/core/authentication_dialog_controller_p.h @@ -42,17 +42,17 @@ #include "base/memory/ref_counted.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.h" +#include "login_delegate_qt.h" namespace QtWebEngineCore { class AuthenticationDialogControllerPrivate { public: - AuthenticationDialogControllerPrivate(ResourceDispatcherHostLoginDelegateQt *loginDelegate); + AuthenticationDialogControllerPrivate(LoginDelegateQt *loginDelegate); void dialogFinished(bool accepted, const QString &user = QString(), const QString &password = QString()); - scoped_refptr<ResourceDispatcherHostLoginDelegateQt> loginDelegate; + scoped_refptr<LoginDelegateQt> loginDelegate; }; } // namespace QtWebEngineCore diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp index 50319e11c..644a0a9f0 100644 --- a/src/core/browser_accessibility_manager_qt.cpp +++ b/src/core/browser_accessibility_manager_qt.cpp @@ -39,7 +39,7 @@ #include "browser_accessibility_manager_qt.h" -#include "third_party/WebKit/public/web/WebAXEnums.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "browser_accessibility_qt.h" using namespace blink; @@ -52,18 +52,19 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create( BrowserAccessibilityFactory* factory) { #ifndef QT_NO_ACCESSIBILITY - return new BrowserAccessibilityManagerQt(0, initialTree, delegate); + return new BrowserAccessibilityManagerQt(nullptr, initialTree, delegate, factory); #else - return 0; + delete factory; + return nullptr; #endif // QT_NO_ACCESSIBILITY } -BrowserAccessibility *BrowserAccessibilityFactoryQt::Create() +BrowserAccessibility *BrowserAccessibility::Create() { #ifndef QT_NO_ACCESSIBILITY return new BrowserAccessibilityQt(); #else - return 0; + return nullptr; #endif // QT_NO_ACCESSIBILITY } @@ -82,25 +83,25 @@ QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible() return QAccessible::queryAccessibleInterface(m_parentObject); } -void BrowserAccessibilityManagerQt::FireBlinkEvent(ui::AXEvent event_type, +void BrowserAccessibilityManagerQt::FireBlinkEvent(ax::mojom::Event event_type, BrowserAccessibility* node) { BrowserAccessibilityQt *iface = static_cast<BrowserAccessibilityQt*>(node); switch (event_type) { - case ui::AX_EVENT_FOCUS: { + case ax::mojom::Event::kFocus: { QAccessibleEvent event(iface, QAccessible::Focus); QAccessible::updateAccessibility(&event); break; } - case ui::AX_EVENT_CHECKED_STATE_CHANGED: { + case ax::mojom::Event::kCheckedStateChanged: { QAccessible::State change; change.checked = true; QAccessibleStateChangeEvent event(iface, change); QAccessible::updateAccessibility(&event); break; } - case ui::AX_EVENT_VALUE_CHANGED: { + case ax::mojom::Event::kValueChanged: { QVariant value; if (QAccessibleValueInterface *valueIface = iface->valueInterface()) value = valueIface->currentValue(); @@ -108,18 +109,18 @@ void BrowserAccessibilityManagerQt::FireBlinkEvent(ui::AXEvent event_type, QAccessible::updateAccessibility(&event); break; } - case ui::AX_EVENT_CHILDREN_CHANGED: + case ax::mojom::Event::kChildrenChanged: break; - case ui::AX_EVENT_LAYOUT_COMPLETE: + case ax::mojom::Event::kLayoutComplete: break; - case ui::AX_EVENT_LOAD_COMPLETE: + case ax::mojom::Event::kLoadComplete: break; - case ui::AX_EVENT_TEXT_CHANGED: { + case ax::mojom::Event::kTextChanged: { QAccessibleTextUpdateEvent event(iface, -1, QString(), QString()); QAccessible::updateAccessibility(&event); break; } - case ui::AX_EVENT_TEXT_SELECTION_CHANGED: { + case ax::mojom::Event::kTextSelectionChanged: { QAccessibleTextInterface *textIface = iface->textInterface(); if (textIface) { int start = 0; diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h index e2315d98a..a2d6db458 100644 --- a/src/core/browser_accessibility_manager_qt.h +++ b/src/core/browser_accessibility_manager_qt.h @@ -50,20 +50,14 @@ QT_END_NAMESPACE namespace content { -class BrowserAccessibilityFactoryQt : public BrowserAccessibilityFactory -{ -public: - BrowserAccessibility* Create() override; -}; - class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager { public: BrowserAccessibilityManagerQt(QObject* parentObject, const ui::AXTreeUpdate& initialTree, BrowserAccessibilityDelegate* delegate, - BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactoryQt()); - void FireBlinkEvent(ui::AXEvent event_type, + BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory()); + void FireBlinkEvent(ax::mojom::Event event_type, BrowserAccessibility* node) override; QAccessibleInterface *rootParentAccessible(); diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 674b323d0..a672ccc06 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -45,8 +45,7 @@ #ifndef QT_NO_ACCESSIBILITY -#include "third_party/WebKit/public/web/WebAXEnums.h" -#include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "browser_accessibility_manager_qt.h" #include "qtwebenginecoreglobal_p.h" @@ -57,6 +56,11 @@ using QtWebEngineCore::toQt; namespace content { +const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibility *obj) +{ + return static_cast<const BrowserAccessibilityQt *>(obj); +} + BrowserAccessibilityQt::BrowserAccessibilityQt() { QAccessible::registerAccessibleInterface(this); @@ -91,7 +95,7 @@ void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type) return static_cast<QAccessibleActionInterface*>(this); break; case QAccessible::TextInterface: - if (HasState(ui::AX_STATE_EDITABLE)) + if (HasState(ax::mojom::State::kEditable)) return static_cast<QAccessibleTextInterface*>(this); break; case QAccessible::ValueInterface: { @@ -154,13 +158,13 @@ QString BrowserAccessibilityQt::text(QAccessible::Text t) const { switch (t) { case QAccessible::Name: - return toQt(GetStringAttribute(ui::AX_ATTR_NAME)); + return toQt(GetStringAttribute(ax::mojom::StringAttribute::kName)); case QAccessible::Description: - return toQt(GetStringAttribute(ui::AX_ATTR_DESCRIPTION)); + return toQt(GetStringAttribute(ax::mojom::StringAttribute::kDescription)); case QAccessible::Value: - return toQt(GetStringAttribute(ui::AX_ATTR_VALUE)); + return toQt(GetStringAttribute(ax::mojom::StringAttribute::kValue)); case QAccessible::Accelerator: - return toQt(GetStringAttribute(ui::AX_ATTR_KEY_SHORTCUTS)); + return toQt(GetStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)); default: break; } @@ -175,267 +179,321 @@ QRect BrowserAccessibilityQt::rect() const { if (!manager()) // needed implicitly by GetScreenBoundsRect() return QRect(); - gfx::Rect bounds = GetScreenBoundsRect(); + gfx::Rect bounds = GetUnclippedScreenBoundsRect(); return QRect(bounds.x(), bounds.y(), bounds.width(), bounds.height()); } QAccessible::Role BrowserAccessibilityQt::role() const { switch (GetRole()) { - case ui::AX_ROLE_NONE: - case ui::AX_ROLE_UNKNOWN: + case ax::mojom::Role::kNone: + case ax::mojom::Role::kUnknown: return QAccessible::NoRole; // Used by Chromium to distinguish between the root of the tree // for this page, and a web area for a frame within this page. - case ui::AX_ROLE_WEB_AREA: - case ui::AX_ROLE_WEB_VIEW: - case ui::AX_ROLE_ROOT_WEB_AREA: // not sure if we need to make a diff here, but this seems common + case ax::mojom::Role::kWebArea: + case ax::mojom::Role::kWebView: + case ax::mojom::Role::kRootWebArea: // not sure if we need to make a diff here, but this seems common return QAccessible::WebDocument; // These roles all directly correspond to blink accessibility roles, // keep these alphabetical. - case ui::AX_ROLE_ABBR: + case ax::mojom::Role::kAbbr: return QAccessible::StaticText; - case ui::AX_ROLE_ALERT: - case ui::AX_ROLE_ALERT_DIALOG: + case ax::mojom::Role::kAlert: + case ax::mojom::Role::kAlertDialog: return QAccessible::AlertMessage; - case ui::AX_ROLE_ANCHOR: + case ax::mojom::Role::kAnchor: return QAccessible::Link; - case ui::AX_ROLE_ANNOTATION: + case ax::mojom::Role::kAnnotation: return QAccessible::StaticText; - case ui::AX_ROLE_APPLICATION: + case ax::mojom::Role::kApplication: return QAccessible::Document; // returning Application here makes Qt return the top level app object - case ui::AX_ROLE_ARTICLE: + case ax::mojom::Role::kArticle: return QAccessible::Section; - case ui::AX_ROLE_AUDIO: + case ax::mojom::Role::kAudio: return QAccessible::Sound; - case ui::AX_ROLE_BANNER: + case ax::mojom::Role::kBanner: return QAccessible::Section; - case ui::AX_ROLE_BLOCKQUOTE: + case ax::mojom::Role::kBlockquote: return QAccessible::Section; - case ui::AX_ROLE_BUTTON: + case ax::mojom::Role::kButton: return QAccessible::Button; - case ui::AX_ROLE_BUTTON_DROP_DOWN: - // TODO: Remove this during the next Chromium update: https://chromium-review.googlesource.com/842475 - return QAccessible::ButtonDropDown; - case ui::AX_ROLE_CANVAS: + case ax::mojom::Role::kCanvas: return QAccessible::Canvas; - case ui::AX_ROLE_CAPTION: + case ax::mojom::Role::kCaption: return QAccessible::Heading; - case ui::AX_ROLE_CARET: + case ax::mojom::Role::kCaret: return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003 - case ui::AX_ROLE_CELL: + case ax::mojom::Role::kCell: return QAccessible::Cell; - case ui::AX_ROLE_CHECK_BOX: + case ax::mojom::Role::kCheckBox: return QAccessible::CheckBox; - case ui::AX_ROLE_CLIENT: + case ax::mojom::Role::kClient: return QAccessible::Client; - case ui::AX_ROLE_COLOR_WELL: + case ax::mojom::Role::kColorWell: return QAccessible::ColorChooser; - case ui::AX_ROLE_COLUMN: + case ax::mojom::Role::kColumn: return QAccessible::Column; - case ui::AX_ROLE_COLUMN_HEADER: + case ax::mojom::Role::kColumnHeader: return QAccessible::ColumnHeader; - case ui::AX_ROLE_COMBO_BOX_GROUPING: - case ui::AX_ROLE_COMBO_BOX_MENU_BUTTON: - case ui::AX_ROLE_TEXT_FIELD_WITH_COMBO_BOX: + case ax::mojom::Role::kComboBoxGrouping: + case ax::mojom::Role::kComboBoxMenuButton: + case ax::mojom::Role::kTextFieldWithComboBox: return QAccessible::ComboBox; - case ui::AX_ROLE_COMPLEMENTARY: + case ax::mojom::Role::kComplementary: return QAccessible::ComplementaryContent; - case ui::AX_ROLE_CONTENT_INFO: + case ax::mojom::Role::kContentDeletion: + case ax::mojom::Role::kContentInsertion: + return QAccessible::Grouping; + case ax::mojom::Role::kContentInfo: return QAccessible::Section; - case ui::AX_ROLE_DATE: - case ui::AX_ROLE_DATE_TIME: + case ax::mojom::Role::kDate: + case ax::mojom::Role::kDateTime: return QAccessible::Clock; - case ui::AX_ROLE_DEFINITION: + case ax::mojom::Role::kDefinition: return QAccessible::Paragraph; - case ui::AX_ROLE_DESCRIPTION_LIST: + case ax::mojom::Role::kDescriptionList: return QAccessible::List; - case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL: + case ax::mojom::Role::kDescriptionListDetail: return QAccessible::Paragraph; - case ui::AX_ROLE_DETAILS: - return QAccessible::Grouping; - case ui::AX_ROLE_DESCRIPTION_LIST_TERM: + case ax::mojom::Role::kDescriptionListTerm: return QAccessible::ListItem; - case ui::AX_ROLE_DESKTOP: + case ax::mojom::Role::kDetails: + return QAccessible::Grouping; + case ax::mojom::Role::kDesktop: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_DIALOG: + case ax::mojom::Role::kDialog: return QAccessible::Dialog; - case ui::AX_ROLE_DIRECTORY: + case ax::mojom::Role::kDirectory: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_DISCLOSURE_TRIANGLE: + case ax::mojom::Role::kDisclosureTriangle: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_GENERIC_CONTAINER: + case ax::mojom::Role::kGenericContainer: return QAccessible::Section; - case ui::AX_ROLE_DOCUMENT: + case ax::mojom::Role::kDocCover: + return QAccessible::Graphic; + case ax::mojom::Role::kDocBackLink: + case ax::mojom::Role::kDocBiblioRef: + case ax::mojom::Role::kDocGlossRef: + case ax::mojom::Role::kDocNoteRef: + return QAccessible::Link; + case ax::mojom::Role::kDocBiblioEntry: + case ax::mojom::Role::kDocEndnote: + case ax::mojom::Role::kDocFootnote: + return QAccessible::ListItem; + case ax::mojom::Role::kDocPageBreak: + return QAccessible::Separator; + case ax::mojom::Role::kDocAbstract: + case ax::mojom::Role::kDocAcknowledgments: + case ax::mojom::Role::kDocAfterword: + case ax::mojom::Role::kDocAppendix: + case ax::mojom::Role::kDocBibliography: + case ax::mojom::Role::kDocChapter: + case ax::mojom::Role::kDocColophon: + case ax::mojom::Role::kDocConclusion: + case ax::mojom::Role::kDocCredit: + case ax::mojom::Role::kDocCredits: + case ax::mojom::Role::kDocDedication: + case ax::mojom::Role::kDocEndnotes: + case ax::mojom::Role::kDocEpigraph: + case ax::mojom::Role::kDocEpilogue: + case ax::mojom::Role::kDocErrata: + case ax::mojom::Role::kDocExample: + case ax::mojom::Role::kDocForeword: + case ax::mojom::Role::kDocGlossary: + case ax::mojom::Role::kDocIndex: + case ax::mojom::Role::kDocIntroduction: + case ax::mojom::Role::kDocNotice: + case ax::mojom::Role::kDocPageList: + case ax::mojom::Role::kDocPart: + case ax::mojom::Role::kDocPreface: + case ax::mojom::Role::kDocPrologue: + case ax::mojom::Role::kDocPullquote: + case ax::mojom::Role::kDocQna: + case ax::mojom::Role::kDocSubtitle: + case ax::mojom::Role::kDocTip: + case ax::mojom::Role::kDocToc: + return QAccessible::Section; + case ax::mojom::Role::kDocument: return QAccessible::Document; - case ui::AX_ROLE_EMBEDDED_OBJECT: + case ax::mojom::Role::kEmbeddedObject: return QAccessible::Grouping; // FIXME - case ui::AX_ROLE_FEED: + case ax::mojom::Role::kFeed: return QAccessible::Section; - case ui::AX_ROLE_FIGCAPTION: + case ax::mojom::Role::kFigcaption: return QAccessible::Heading; - case ui::AX_ROLE_FIGURE: + case ax::mojom::Role::kFigure: return QAccessible::Section; - case ui::AX_ROLE_FOOTER: + case ax::mojom::Role::kFooter: return QAccessible::Footer; - case ui::AX_ROLE_FORM: + case ax::mojom::Role::kForm: return QAccessible::Form; - case ui::AX_ROLE_GRID: + case ax::mojom::Role::kGraphicsDocument: + return QAccessible::Document; + case ax::mojom::Role::kGraphicsObject: + return QAccessible::Pane; + case ax::mojom::Role::kGraphicsSymbol: + return QAccessible::Graphic; + case ax::mojom::Role::kGrid: return QAccessible::Table; - case ui::AX_ROLE_GROUP: + case ax::mojom::Role::kGroup: return QAccessible::Grouping; - case ui::AX_ROLE_HEADING: + case ax::mojom::Role::kHeading: return QAccessible::Heading; - case ui::AX_ROLE_IFRAME: + case ax::mojom::Role::kIframe: return QAccessible::Grouping; - case ui::AX_ROLE_IFRAME_PRESENTATIONAL: + case ax::mojom::Role::kIframePresentational: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_IGNORED: + case ax::mojom::Role::kIgnored: return QAccessible::NoRole; - case ui::AX_ROLE_IMAGE: + case ax::mojom::Role::kImage: return QAccessible::Graphic; - case ui::AX_ROLE_IMAGE_MAP: + case ax::mojom::Role::kImageMap: return QAccessible::Graphic; - case ui::AX_ROLE_INLINE_TEXT_BOX: + case ax::mojom::Role::kInlineTextBox: return QAccessible::EditableText; - case ui::AX_ROLE_INPUT_TIME: + case ax::mojom::Role::kInputTime: return QAccessible::SpinBox; - case ui::AX_ROLE_LABEL_TEXT: + case ax::mojom::Role::kLabelText: return QAccessible::StaticText; - case ui::AX_ROLE_LEGEND: + case ax::mojom::Role::kLayoutTable: + case ax::mojom::Role::kLayoutTableCell: + case ax::mojom::Role::kLayoutTableColumn: + case ax::mojom::Role::kLayoutTableRow: + // No role description. + return QAccessible::NoRole; + case ax::mojom::Role::kLegend: return QAccessible::StaticText; - case ui::AX_ROLE_LINE_BREAK: + case ax::mojom::Role::kLineBreak: return QAccessible::Separator; - case ui::AX_ROLE_LINK: + case ax::mojom::Role::kLink: return QAccessible::Link; - case ui::AX_ROLE_LIST: + case ax::mojom::Role::kList: return QAccessible::List; - case ui::AX_ROLE_LIST_BOX: + case ax::mojom::Role::kListBox: return QAccessible::ComboBox; - case ui::AX_ROLE_LIST_BOX_OPTION: + case ax::mojom::Role::kListBoxOption: return QAccessible::ListItem; - case ui::AX_ROLE_LIST_ITEM: + case ax::mojom::Role::kListItem: return QAccessible::ListItem; - case ui::AX_ROLE_LIST_MARKER: + case ax::mojom::Role::kListMarker: return QAccessible::StaticText; - case ui::AX_ROLE_LOCATION_BAR: - return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_LOG: + case ax::mojom::Role::kLog: return QAccessible::Section; - case ui::AX_ROLE_MAIN: + case ax::mojom::Role::kMain: return QAccessible::Grouping; - case ui::AX_ROLE_MARK: + case ax::mojom::Role::kMark: return QAccessible::StaticText; - case ui::AX_ROLE_MARQUEE: + case ax::mojom::Role::kMarquee: return QAccessible::Section; - case ui::AX_ROLE_MATH: + case ax::mojom::Role::kMath: return QAccessible::Equation; - case ui::AX_ROLE_MENU: + case ax::mojom::Role::kMenu: return QAccessible::PopupMenu; - case ui::AX_ROLE_MENU_BAR: + case ax::mojom::Role::kMenuBar: return QAccessible::MenuBar; - case ui::AX_ROLE_MENU_ITEM: + case ax::mojom::Role::kMenuItem: return QAccessible::MenuItem; - case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: + case ax::mojom::Role::kMenuItemCheckBox: return QAccessible::CheckBox; - case ui::AX_ROLE_MENU_ITEM_RADIO: + case ax::mojom::Role::kMenuItemRadio: return QAccessible::RadioButton; - case ui::AX_ROLE_MENU_BUTTON: + case ax::mojom::Role::kMenuButton: return QAccessible::MenuItem; - case ui::AX_ROLE_MENU_LIST_OPTION: + case ax::mojom::Role::kMenuListOption: return QAccessible::MenuItem; - case ui::AX_ROLE_MENU_LIST_POPUP: + case ax::mojom::Role::kMenuListPopup: return QAccessible::PopupMenu; - case ui::AX_ROLE_METER: + case ax::mojom::Role::kMeter: return QAccessible::Chart; - case ui::AX_ROLE_NAVIGATION: + case ax::mojom::Role::kNavigation: return QAccessible::Section; - case ui::AX_ROLE_NOTE: + case ax::mojom::Role::kNote: return QAccessible::Note; - case ui::AX_ROLE_PANE: + case ax::mojom::Role::kPane: return QAccessible::Pane; - case ui::AX_ROLE_PARAGRAPH: + case ax::mojom::Role::kParagraph: return QAccessible::Paragraph; - case ui::AX_ROLE_POP_UP_BUTTON: + case ax::mojom::Role::kPopUpButton: return QAccessible::ComboBox; - case ui::AX_ROLE_PRE: + case ax::mojom::Role::kPre: return QAccessible::Section; - case ui::AX_ROLE_PRESENTATIONAL: + case ax::mojom::Role::kPresentational: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_PROGRESS_INDICATOR: + case ax::mojom::Role::kProgressIndicator: return QAccessible::ProgressBar; - case ui::AX_ROLE_RADIO_BUTTON: + case ax::mojom::Role::kRadioButton: return QAccessible::RadioButton; - case ui::AX_ROLE_RADIO_GROUP: + case ax::mojom::Role::kRadioGroup: return QAccessible::Grouping; - case ui::AX_ROLE_REGION: + case ax::mojom::Role::kRegion: return QAccessible::Section; - case ui::AX_ROLE_ROW: + case ax::mojom::Role::kRow: return QAccessible::Row; - case ui::AX_ROLE_ROW_HEADER: + case ax::mojom::Role::kRowHeader: return QAccessible::RowHeader; - case ui::AX_ROLE_RUBY: + case ax::mojom::Role::kRuby: return QAccessible::StaticText; - case ui::AX_ROLE_SCROLL_BAR: + case ax::mojom::Role::kScrollBar: return QAccessible::ScrollBar; - case ui::AX_ROLE_SEARCH: + case ax::mojom::Role::kScrollView: + return QAccessible::NoRole; // FIXME + case ax::mojom::Role::kSearch: return QAccessible::Section; - case ui::AX_ROLE_SEARCH_BOX: + case ax::mojom::Role::kSearchBox: return QAccessible::EditableText; - case ui::AX_ROLE_SLIDER: + case ax::mojom::Role::kSlider: return QAccessible::Slider; - case ui::AX_ROLE_SLIDER_THUMB: + case ax::mojom::Role::kSliderThumb: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_SPIN_BUTTON: + case ax::mojom::Role::kSpinButton: return QAccessible::SpinBox; - case ui::AX_ROLE_SPIN_BUTTON_PART: - return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_SPLITTER: + case ax::mojom::Role::kSplitter: return QAccessible::Splitter; - case ui::AX_ROLE_STATIC_TEXT: + case ax::mojom::Role::kStaticText: return QAccessible::StaticText; - case ui::AX_ROLE_STATUS: + case ax::mojom::Role::kStatus: return QAccessible::Indicator; - case ui::AX_ROLE_SVG_ROOT: + case ax::mojom::Role::kSvgRoot: return QAccessible::Graphic; - case ui::AX_ROLE_SWITCH: + case ax::mojom::Role::kSwitch: return QAccessible::Button; - case ui::AX_ROLE_TABLE: + case ax::mojom::Role::kTable: return QAccessible::Table; - case ui::AX_ROLE_TABLE_HEADER_CONTAINER: + case ax::mojom::Role::kTableHeaderContainer: return QAccessible::Section; - case ui::AX_ROLE_TAB: + case ax::mojom::Role::kTab: return QAccessible::PageTab; - case ui::AX_ROLE_TAB_LIST: + case ax::mojom::Role::kTabList: return QAccessible::PageTabList; - case ui::AX_ROLE_TAB_PANEL: + case ax::mojom::Role::kTabPanel: return QAccessible::PageTab; - case ui::AX_ROLE_TERM: + case ax::mojom::Role::kTerm: return QAccessible::StaticText; - case ui::AX_ROLE_TEXT_FIELD: + case ax::mojom::Role::kTextField: return QAccessible::EditableText; - case ui::AX_ROLE_TIME: - case ui::AX_ROLE_TIMER: + case ax::mojom::Role::kTime: + case ax::mojom::Role::kTimer: return QAccessible::Clock; - case ui::AX_ROLE_TITLE_BAR: + case ax::mojom::Role::kTitleBar: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_TOGGLE_BUTTON: + case ax::mojom::Role::kToggleButton: return QAccessible::Button; - case ui::AX_ROLE_TOOLBAR: + case ax::mojom::Role::kToolbar: return QAccessible::ToolBar; - case ui::AX_ROLE_TOOLTIP: + case ax::mojom::Role::kTooltip: return QAccessible::ToolTip; - case ui::AX_ROLE_TREE: + case ax::mojom::Role::kTree: return QAccessible::Tree; - case ui::AX_ROLE_TREE_GRID: + case ax::mojom::Role::kTreeGrid: return QAccessible::Tree; - case ui::AX_ROLE_TREE_ITEM: + case ax::mojom::Role::kTreeItem: return QAccessible::TreeItem; - case ui::AX_ROLE_VIDEO: + case ax::mojom::Role::kVideo: return QAccessible::Animation; - case ui::AX_ROLE_WINDOW: + case ax::mojom::Role::kWindow: return QAccessible::Window; } return QAccessible::NoRole; @@ -444,79 +502,100 @@ QAccessible::Role BrowserAccessibilityQt::role() const QAccessible::State BrowserAccessibilityQt::state() const { QAccessible::State state = QAccessible::State(); - int32_t s = GetState(); - if (s & (1 << ui::AX_STATE_COLLAPSED)) + if (HasState(ax::mojom::State::kCollapsed)) state.collapsed = true; - if (s & (1 << ui::AX_STATE_DEFAULT)) + if (HasState(ax::mojom::State::kDefault)) state.defaultButton = true; - if (s & (1 << ui::AX_STATE_EDITABLE)) + if (HasState(ax::mojom::State::kEditable)) state.editable = true; - if (s & (1 << ui::AX_STATE_EXPANDED)) + if (HasState(ax::mojom::State::kExpanded)) state.expanded = true; - if (s & (1 << ui::AX_STATE_FOCUSABLE)) + if (HasState(ax::mojom::State::kFocusable)) state.focusable = true; - if (s & (1 << ui::AX_STATE_HASPOPUP)) - state.hasPopup = true; - if (s & (1 << ui::AX_STATE_HOVERED)) + if (HasState(ax::mojom::State::kHorizontal)) + {} // FIXME + if (HasState(ax::mojom::State::kHovered)) state.hotTracked = true; - if (s & (1 << ui::AX_STATE_INVISIBLE)) + if (HasState(ax::mojom::State::kIgnored)) + {} // FIXME + if (HasState(ax::mojom::State::kInvisible)) state.invisible = true; - if (s & (1 << ui::AX_STATE_LINKED)) + if (HasState(ax::mojom::State::kLinked)) state.linked = true; - if (s & (1 << ui::AX_STATE_MULTISELECTABLE)) + if (HasState(ax::mojom::State::kMultiline)) + state.multiLine = true; + if (HasState(ax::mojom::State::kMultiselectable)) state.multiSelectable = true; - if (s & (1 << ui::AX_STATE_PROTECTED)) - {} // FIXME - if (s & (1 << ui::AX_STATE_REQUIRED)) + if (HasState(ax::mojom::State::kProtected)) + state.passwordEdit = true; + if (HasState(ax::mojom::State::kRequired)) {} // FIXME - if (s & (1 << ui::AX_STATE_RICHLY_EDITABLE)) + if (HasState(ax::mojom::State::kRichlyEditable)) {} // FIXME - if (s & (1 << ui::AX_STATE_SELECTABLE)) - state.selectable = true; - if (s & (1 << ui::AX_STATE_SELECTED)) - state.selected = true; - if (s & (1 << ui::AX_STATE_VERTICAL)) - {} // FIXME - if (s & (1 << ui::AX_STATE_VISITED)) + if (HasState(ax::mojom::State::kVertical)) {} // FIXME + if (HasState(ax::mojom::State::kVisited)) + state.traversed = true; if (IsOffscreen()) state.offscreen = true; if (manager()->GetFocus() == this) state.focused = true; - if (GetBoolAttribute(ui::AX_ATTR_BUSY)) + if (GetBoolAttribute(ax::mojom::BoolAttribute::kBusy)) state.busy = true; - if (HasIntAttribute(ui::AX_ATTR_CHECKED_STATE)) { - ui::AXCheckedState checkedState = (ui::AXCheckedState)GetIntAttribute(ui::AX_ATTR_CHECKED_STATE); + if (GetBoolAttribute(ax::mojom::BoolAttribute::kModal)) + state.modal = true; + if (HasBoolAttribute(ax::mojom::BoolAttribute::kSelected)) { + state.selectable = true; + state.selected = GetBoolAttribute(ax::mojom::BoolAttribute::kSelected); + } + if (HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) { + state.checkable = true; + const ax::mojom::CheckedState checkedState = + static_cast<ax::mojom::CheckedState>(GetIntAttribute(ax::mojom::IntAttribute::kCheckedState)); switch (checkedState) { - case ui::AX_CHECKED_STATE_TRUE: - if (GetRole() == ui::AX_ROLE_TOGGLE_BUTTON) + case ax::mojom::CheckedState::kTrue: + if (GetRole() == ax::mojom::Role::kToggleButton) state.pressed = true; else state.checked = true; break; - case ui::AX_CHECKED_STATE_MIXED: + case ax::mojom::CheckedState::kMixed: state.checkStateMixed = true; break; - case ui::AX_CHECKED_STATE_FALSE: - case ui::AX_CHECKED_STATE_NONE: + case ax::mojom::CheckedState::kFalse: + case ax::mojom::CheckedState::kNone: break; } } - if (HasIntAttribute(ui::AX_ATTR_RESTRICTION)) { - ui::AXRestriction restriction = (ui::AXRestriction)GetIntAttribute(ui::AX_ATTR_RESTRICTION); + if (HasIntAttribute(ax::mojom::IntAttribute::kRestriction)) { + const ax::mojom::Restriction restriction = static_cast<ax::mojom::Restriction>(GetIntAttribute(ax::mojom::IntAttribute::kRestriction)); switch (restriction) { - case ui::AX_RESTRICTION_READ_ONLY: + case ax::mojom::Restriction::kReadOnly: state.readOnly = true; break; - case ui::AX_RESTRICTION_DISABLED: + case ax::mojom::Restriction::kDisabled: state.disabled = true; break; - case ui::AX_RESTRICTION_NONE: + case ax::mojom::Restriction::kNone: + break; + } + } + if (HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) { + const ax::mojom::HasPopup hasPopup = static_cast<ax::mojom::HasPopup>(GetIntAttribute(ax::mojom::IntAttribute::kHasPopup)); + switch (hasPopup) { + case ax::mojom::HasPopup::kFalse: + break; + case ax::mojom::HasPopup::kTrue: + case ax::mojom::HasPopup::kMenu: + case ax::mojom::HasPopup::kListbox: + case ax::mojom::HasPopup::kTree: + case ax::mojom::HasPopup::kGrid: + case ax::mojom::HasPopup::kDialog: + state.hasPopup = true; break; } } - return state; } @@ -539,7 +618,7 @@ void BrowserAccessibilityQt::NativeReleaseReference() QStringList BrowserAccessibilityQt::actionNames() const { QStringList actions; - if (HasState(ui::AX_STATE_FOCUSABLE)) + if (HasState(ax::mojom::State::kFocusable)) actions << QAccessibleActionInterface::setFocusAction(); return actions; } @@ -571,7 +650,7 @@ QString BrowserAccessibilityQt::attributes(int offset, int *startOffset, int *en int BrowserAccessibilityQt::cursorPosition() const { int pos = 0; - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &pos); + GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &pos); return pos; } @@ -585,8 +664,8 @@ int BrowserAccessibilityQt::selectionCount() const { int start = 0; int end = 0; - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); + GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &start); + GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &end); if (start != end) return 1; return 0; @@ -605,8 +684,8 @@ void BrowserAccessibilityQt::selection(int selectionIndex, int *startOffset, int *endOffset = 0; if (selectionIndex != 0) return; - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, startOffset); - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, endOffset); + GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, startOffset); + GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, endOffset); } QString BrowserAccessibilityQt::text(int startOffset, int endOffset) const @@ -647,7 +726,7 @@ QVariant BrowserAccessibilityQt::currentValue() const { QVariant result; float value; - if (GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &value)) { + if (GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, &value)) { result = (double) value; } return result; @@ -663,7 +742,7 @@ QVariant BrowserAccessibilityQt::maximumValue() const { QVariant result; float value; - if (GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE, &value)) { + if (GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, &value)) { result = (double) value; } return result; @@ -673,7 +752,7 @@ QVariant BrowserAccessibilityQt::minimumValue() const { QVariant result; float value; - if (GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE, &value)) { + if (GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, &value)) { result = (double) value; } return result; @@ -681,15 +760,20 @@ QVariant BrowserAccessibilityQt::minimumValue() const QVariant BrowserAccessibilityQt::minimumStepSize() const { - return QVariant(); + QVariant result; + float value; + if (GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, &value)) { + result = (double) value; + } + return result; } QAccessibleInterface *BrowserAccessibilityQt::cellAt(int row, int column) const { int columns = 0; int rows = 0; - if (!GetIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, &columns) || - !GetIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, &rows) || + if (!GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns) || + !GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows) || columns <= 0 || rows <= 0) { return 0; @@ -698,10 +782,7 @@ QAccessibleInterface *BrowserAccessibilityQt::cellAt(int row, int column) const if (row < 0 || row >= rows || column < 0 || column >= columns) return 0; - const std::vector<int32_t>& cell_ids = GetIntListAttribute(ui::AX_ATTR_CELL_IDS); - DCHECK_EQ(columns * rows, static_cast<int>(cell_ids.size())); - - int cell_id = cell_ids[row * columns + column]; + int cell_id = GetCellId(row, column); BrowserAccessibility* cell = manager()->GetFromID(cell_id); if (cell) { QAccessibleInterface *iface = static_cast<BrowserAccessibilityQt*>(cell); @@ -734,7 +815,7 @@ QString BrowserAccessibilityQt::rowDescription(int row) const int BrowserAccessibilityQt::columnCount() const { int columns = 0; - if (GetIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, &columns)) + if (GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns)) return columns; return 0; @@ -743,7 +824,7 @@ int BrowserAccessibilityQt::columnCount() const int BrowserAccessibilityQt::rowCount() const { int rows = 0; - if (GetIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, &rows)) + if (GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows)) return rows; return 0; } @@ -821,7 +902,7 @@ QList<QAccessibleInterface *> BrowserAccessibilityQt::columnHeaderCells() const int BrowserAccessibilityQt::columnIndex() const { int column = 0; - if (GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX, &column)) + if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, &column)) return column; return 0; } @@ -839,7 +920,7 @@ QList<QAccessibleInterface *> BrowserAccessibilityQt::rowHeaderCells() const int BrowserAccessibilityQt::rowIndex() const { int row = 0; - if (GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX, &row)) + if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row)) return row; return 0; } @@ -852,7 +933,7 @@ bool BrowserAccessibilityQt::isSelected() const QAccessibleInterface *BrowserAccessibilityQt::table() const { BrowserAccessibility* find_table = PlatformGetParent(); - while (find_table && find_table->GetRole() != ui::AX_ROLE_TABLE) + while (find_table && find_table->GetRole() != ax::mojom::Role::kTable) find_table = find_table->PlatformGetParent(); if (!find_table) return 0; diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index 167165ac0..345ee9862 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -41,9 +41,10 @@ #define BROWSER_ACCESSIBILITY_QT_H #include <QtGui/qaccessible.h> -#ifndef QT_NO_ACCESSIBILITY #include "content/browser/accessibility/browser_accessibility.h" +#ifndef QT_NO_ACCESSIBILITY + namespace content { class BrowserAccessibilityQt @@ -144,7 +145,9 @@ public: void modelChange(QAccessibleTableModelChangeEvent *event) override; }; -} +const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibility *obj); + +} // namespace content #endif // QT_NO_ACCESSIBILITY #endif diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp new file mode 100644 index 000000000..38e048470 --- /dev/null +++ b/src/core/browser_main_parts_qt.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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_main_parts_qt.h" + +#include "base/message_loop/message_loop.h" +#include "base/process/process.h" +#include "base/threading/thread_restrictions.h" +#include "content/public/browser/browser_main_parts.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/service_manager_connection.h" +#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h" +#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service.h" +#include "ui/display/screen.h" + +#include "service/service_qt.h" +#include "web_engine_context.h" + +#include <QCoreApplication> +#include <QEvent> +#include <QEventLoop> +#include <QObject> +#include <QTimerEvent> + +#if defined(Q_OS_WIN) +#include "ui/display/win/screen_win.h" +#else +#include "desktop_screen_qt.h" +#endif + + +namespace QtWebEngineCore { + +namespace { + +// Return a timeout suitable for the glib loop, -1 to block forever, +// 0 to return right away, or a timeout in milliseconds from now. +int GetTimeIntervalMilliseconds(const base::TimeTicks &from) +{ + if (from.is_null()) + return -1; + + // Be careful here. TimeDelta has a precision of microseconds, but we want a + // value in milliseconds. If there are 5.5ms left, should the delay be 5 or + // 6? It should be 6 to avoid executing delayed work too early. + int delay = static_cast<int>(std::ceil((from - base::TimeTicks::Now()).InMillisecondsF())); + + // If this value is negative, then we need to run delayed work soon. + return delay < 0 ? 0 : delay; +} + +class MessagePumpForUIQt : public QObject, + public base::MessagePump +{ +public: + MessagePumpForUIQt() + : m_delegate(nullptr) + , m_explicitLoop(nullptr) + , m_timerId(0) + { + } + + void Run(Delegate *delegate) override + { + if (!m_delegate) + m_delegate = delegate; + else + Q_ASSERT(delegate == m_delegate); + // This is used only when MessagePumpForUIQt is used outside of the GUI thread. + QEventLoop loop; + m_explicitLoop = &loop; + loop.exec(); + m_explicitLoop = nullptr; + } + + void Quit() override + { + Q_ASSERT(m_explicitLoop); + m_explicitLoop->quit(); + } + + void ScheduleWork() override + { + if (!m_delegate) + m_delegate = base::MessageLoopForUI::current(); + QCoreApplication::postEvent(this, new QTimerEvent(0)); + m_timerScheduledTime = base::TimeTicks::Now(); + } + + void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) override + { + if (!m_delegate) + m_delegate = base::MessageLoopForUI::current(); + if (delayed_work_time.is_null()) { + killTimer(m_timerId); + m_timerId = 0; + m_timerScheduledTime = base::TimeTicks(); + } else if (!m_timerId || delayed_work_time < m_timerScheduledTime) { + killTimer(m_timerId); + m_timerId = startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); + m_timerScheduledTime = delayed_work_time; + } + } + +protected: + void timerEvent(QTimerEvent *ev) override + { + Q_ASSERT(!ev->timerId() || m_timerId == ev->timerId()); + killTimer(m_timerId); + m_timerId = 0; + m_timerScheduledTime = base::TimeTicks(); + + handleScheduledWork(); + } + +private: + void handleScheduledWork() + { + bool more_work_is_plausible = m_delegate->DoWork(); + + base::TimeTicks delayed_work_time; + more_work_is_plausible |= m_delegate->DoDelayedWork(&delayed_work_time); + + if (more_work_is_plausible) + return ScheduleWork(); + + more_work_is_plausible |= m_delegate->DoIdleWork(); + if (more_work_is_plausible) + return ScheduleWork(); + + ScheduleDelayedWork(delayed_work_time); + } + + Delegate *m_delegate; + QEventLoop *m_explicitLoop; + int m_timerId; + base::TimeTicks m_timerScheduledTime; +}; + +} // anonymous namespace + +std::unique_ptr<base::MessagePump> messagePumpFactory() +{ + return base::WrapUnique(new MessagePumpForUIQt); +} + +BrowserMainPartsQt::BrowserMainPartsQt() : content::BrowserMainParts() +{ } + +BrowserMainPartsQt::~BrowserMainPartsQt() = default; + + +int BrowserMainPartsQt::PreEarlyInitialization() +{ + base::MessageLoop::InitMessagePumpForUIFactory(messagePumpFactory); + return 0; +} + +void BrowserMainPartsQt::PreMainMessageLoopStart() +{ +} + +void BrowserMainPartsQt::PostMainMessageLoopRun() +{ + // The BrowserContext's destructor uses the MessageLoop so it should be deleted + // right before the RenderProcessHostImpl's destructor destroys it. + WebEngineContext::current()->destroyBrowserContext(); +} + +int BrowserMainPartsQt::PreCreateThreads() +{ + base::ThreadRestrictions::SetIOAllowed(true); + // Like ChromeBrowserMainExtraPartsViews::PreCreateThreads does. +#if defined(Q_OS_WIN) + display::Screen::SetScreenInstance(new display::win::ScreenWin); +#else + display::Screen::SetScreenInstance(new DesktopScreenQt); +#endif + return 0; +} + +void BrowserMainPartsQt::ServiceManagerConnectionStarted(content::ServiceManagerConnection *connection) +{ + ServiceQt::GetInstance()->InitConnector(); + connection->GetConnector()->StartService(service_manager::Identity("qtwebengine")); + if (resource_coordinator::IsResourceCoordinatorEnabled()) { + m_processResourceCoordinator = std::make_unique<resource_coordinator::ProcessResourceCoordinator>(connection->GetConnector()); + m_processResourceCoordinator->SetLaunchTime(base::Time::Now()); + m_processResourceCoordinator->SetPID(base::Process::Current().Pid()); + } +} + +} // namespace QtWebEngineCore diff --git a/src/core/api/qwebenginebrowsercontext.cpp b/src/core/browser_main_parts_qt.h index c3ab16460..04ca9483d 100644 --- a/src/core/api/qwebenginebrowsercontext.cpp +++ b/src/core/browser_main_parts_qt.h @@ -37,37 +37,44 @@ ** ****************************************************************************/ -#include "qwebenginebrowsercontext_p.h" +#ifndef BROWSER_MAIN_PARTS_QT_H +#define BROWSER_MAIN_PARTS_QT_H -#include "browser_context_adapter.h" -#include <qtwebenginecoreglobal.h> +#include "content/public/browser/browser_main_parts.h" -QT_BEGIN_NAMESPACE +namespace base { +class MessagePump; +} -QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, - QtWebEngineCore::BrowserContextAdapterClient *profile) - : QObject(QtWebEngineCore::BrowserContextAdapter::globalQObjectRoot()) - , browserContextRef(browserContext) - , m_profile(profile) -{ - browserContextRef->addClient(m_profile); +namespace content { +class ServiceManagerConnection; } -QWebEngineBrowserContext::~QWebEngineBrowserContext() -{ - if (m_profile) - shutdown(); +namespace resource_coordinator { +class ProcessResourceCoordinator; } -void QWebEngineBrowserContext::shutdown() +namespace QtWebEngineCore { + +std::unique_ptr<base::MessagePump> messagePumpFactory(); + +class BrowserMainPartsQt : public content::BrowserMainParts { - Q_ASSERT(m_profile); - // In the case the user sets this profile as the parent of the interceptor - // it can be deleted before the browser-context still referencing it is. - browserContextRef->setRequestInterceptor(nullptr); - browserContextRef->removeClient(m_profile); - m_profile = 0; - deleteLater(); -} +public: + BrowserMainPartsQt(); + ~BrowserMainPartsQt(); + + int PreEarlyInitialization() override; + void PreMainMessageLoopStart() override; + void PostMainMessageLoopRun() override; + int PreCreateThreads() override; + void ServiceManagerConnectionStarted(content::ServiceManagerConnection *connection) override; + +private: + DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt); + std::unique_ptr<resource_coordinator::ProcessResourceCoordinator> m_processResourceCoordinator; +}; + +} // namespace QtWebEngineCore -QT_END_NAMESPACE +#endif // BROWSER_MAIN_PARTS_QT_H diff --git a/src/core/browser_message_filter_qt.cpp b/src/core/browser_message_filter_qt.cpp index 330bba3a9..d4fdc4122 100644 --- a/src/core/browser_message_filter_qt.cpp +++ b/src/core/browser_message_filter_qt.cpp @@ -71,39 +71,11 @@ bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_RequestFileSystemAccessAsync, OnRequestFileSystemAccessAsync) IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowIndexedDB, OnAllowIndexedDB) -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) - IPC_MESSAGE_HANDLER( - QtWebEngineHostMsg_IsInternalPluginAvailableForMimeType, - OnIsInternalPluginAvailableForMimeType) -#endif IPC_MESSAGE_UNHANDLED(return false) IPC_END_MESSAGE_MAP() return true; } -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) -void BrowserMessageFilterQt::OnIsInternalPluginAvailableForMimeType( - const std::string& mime_type, - base::Optional<std::vector<content::WebPluginMimeType::Param>> *opt_additional_params) -{ - std::vector<content::WebPluginInfo> plugins; - content::PluginService::GetInstance()->GetInternalPlugins(&plugins); - - for (size_t i = 0; i < plugins.size(); ++i) { - const content::WebPluginInfo& plugin = plugins[i]; - const std::vector<content::WebPluginMimeType>& mime_types = plugin.mime_types; - for (size_t j = 0; j < mime_types.size(); ++j) { - if (mime_types[j].mime_type == mime_type) { - *opt_additional_params = base::make_optional(mime_types[j].additional_params); - return; - } - } - } -} - -#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) - - void BrowserMessageFilterQt::OnAllowDatabase(int /*render_frame_id*/, const GURL &origin_url, const GURL &top_origin_url, diff --git a/src/core/browser_message_filter_qt.h b/src/core/browser_message_filter_qt.h index c05da7944..8b22ab6ac 100644 --- a/src/core/browser_message_filter_qt.h +++ b/src/core/browser_message_filter_qt.h @@ -43,7 +43,6 @@ #include "base/callback.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/common/webplugininfo.h" -#include "media/media_features.h" class GURL; class Profile; @@ -57,18 +56,6 @@ public: private: bool OnMessageReceived(const IPC::Message& message) override; -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) - // Returns whether any internal plugin supporting |mime_type| is registered - // and enabled. Does not determine whether the plugin can actually be - // instantiated (e.g. whether it has all its dependencies). - // When the returned *|is_available| is true, |additional_param_names| and - // |additional_param_values| contain the name-value pairs, if any, specified - // for the *first* non-disabled plugin found that is registered for - // |mime_type|. - void OnIsInternalPluginAvailableForMimeType( - const std::string& mime_type, - base::Optional<std::vector<content::WebPluginMimeType::Param>> *opt_additional_params); -#endif void OnAllowDatabase(int render_frame_id, const GURL &origin_url, diff --git a/src/core/build_config_qt.h b/src/core/build_config_qt.h new file mode 100644 index 000000000..9c7a77d65 --- /dev/null +++ b/src/core/build_config_qt.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 BUILD_CONFIG_QT +#define BUILD_CONFIG_QT + +#include <QtCore/qglobal.h> +#include <QtWebEngineCore/qtwebenginecore-config.h> +#include <QtWebEngineCore/private/qtwebenginecore-config_p.h> + +#include "printing/buildflags/buildflags.h" +#include "components/spellcheck/spellcheck_buildflags.h" +#include "media/media_buildflags.h" +#include "ppapi/buildflags/buildflags.h" + +// This is just config sanity check +#if QT_CONFIG(webengine_printing_and_pdf) +#if !BUILDFLAG(ENABLE_PRINTING) || !BUILDFLAG(ENABLE_PRINT_PREVIEW) +#error Config sanity check for webengine_printing_and_pdf failed +#endif +#else +#if BUILDFLAG(ENABLE_PRINTING) || BUILDFLAG(ENABLE_PRINT_PREVIEW) +#error Config sanity check for ENABLE_PRINTING, ENABLE_PRINT_PREVIEW failed +#endif +#endif + +#if QT_CONFIG(webengine_spellchecker) +#if !BUILDFLAG(ENABLE_SPELLCHECK) +#error Config sanity check for webengine_spellchecker failed +#endif +#else +#if BUILDFLAG(ENABLE_SPELLCHECK) +#error Config sanity check for ENABLE_SPELLCHECK failed +#endif +#endif + +#if QT_CONFIG(webengine_pepper_plugins) +#if !BUILDFLAG(ENABLE_PLUGINS) +#error Config sanity check for webengine_pepper_plugins failed +#endif +#else +#if BUILDFLAG(ENABLE_PLUGINS) +#error Config sanity check for ENABLE_PLUGINS failed +#endif +#endif + +#if QT_CONFIG(webengine_webrtc) +#if !BUILDFLAG(ENABLE_WEBRTC) +#error Config sanity check for webengine_webrtc failed +#endif +#else +#if BUILDFLAG(ENABLE_WEBRTC) +#error Config sanity check for ENABLE_WEBRTC failed +#endif +#endif + +#if QT_CONFIG(webengine_native_spellchecker) +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) +#error Config sanity check for webengine_native_spellchecker failed +#endif +#else +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) +#error Config sanity check for USE_BROWSER_SPELLCHECKER failed +#endif +#endif + +#endif diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index a681de859..a747451df 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -67,6 +67,7 @@ ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateWeakKey, net::ERR_CERT ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateNameConstraintViolation, net::ERR_CERT_NAME_CONSTRAINT_VIOLATION) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateValidityTooLong, net::ERR_CERT_VALIDITY_TOO_LONG) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateTransparencyRequired, net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) +ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateSymantecLegacy, net::ERR_CERT_SYMANTEC_LEGACY) ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateErrorEnd, net::ERR_CERT_END) void CertificateErrorControllerPrivate::accept(bool accepted) diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h index 554281644..6e1e87cb0 100644 --- a/src/core/certificate_error_controller.h +++ b/src/core/certificate_error_controller.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef CERTIFICATE_ERROR_CONTROLLER_H #define CERTIFICATE_ERROR_CONTROLLER_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QtCore/QDateTime> #include <QtCore/QUrl> @@ -49,7 +60,7 @@ QT_BEGIN_NAMESPACE class CertificateErrorControllerPrivate; -class QWEBENGINE_EXPORT CertificateErrorController { +class QWEBENGINECORE_PRIVATE_EXPORT CertificateErrorController { public: CertificateErrorController(CertificateErrorControllerPrivate *p); ~CertificateErrorController(); @@ -72,8 +83,9 @@ public: CertificateNameConstraintViolation = -212, CertificateValidityTooLong = -213, CertificateTransparencyRequired = -214, + CertificateSymantecLegacy = -215, - CertificateErrorEnd = -215 // not an error, just an enum boundary + CertificateErrorEnd = -216 // not an error, just an enum boundary }; CertificateError error() const; diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index 547fbc45c..92a8b13ed 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -57,10 +57,9 @@ #include "content/common/gpu/stream_texture_qnx.h" #endif -// FIXME: Try using content::GpuChildThread::current() -base::MessageLoop *gpu_message_loop() +scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner() { - return content::GpuChildThread::instance()->message_loop(); + return content::GpuChildThread::instance()->main_thread_runner(); } gpu::SyncPointManager *sync_point_manager() diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h index be4380085..21b764997 100644 --- a/src/core/chromium_gpu_helper.h +++ b/src/core/chromium_gpu_helper.h @@ -42,8 +42,10 @@ #include <QtGlobal> // We need this for the Q_OS_QNX define. +#include "base/memory/scoped_refptr.h" + namespace base { -class MessageLoop; +class SingleThreadTaskRunner; } namespace gpu { @@ -58,7 +60,7 @@ class TextureBase; // From the outside, types from incompatible headers referenced in these // functions should only be forward-declared and considered as opaque types. -base::MessageLoop *gpu_message_loop(); +scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner(); gpu::SyncPointManager *sync_point_manager(); gpu::MailboxManager *mailbox_manager(); diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 8f6687ff3..a497ddc46 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -39,19 +39,20 @@ #include "chromium_overrides.h" -#include "gl_context_qt.h" +#include "ozone/gl_context_qt.h" #include "qtwebenginecoreglobal_p.h" #include "web_contents_view_qt.h" #include "base/values.h" #include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/font_list.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/platform/platform_event_source.h" -#include "ppapi/features/features.h" +#include "ppapi/buildflags/buildflags.h" #include <QGuiApplication> #include <QScreen> @@ -59,10 +60,6 @@ #include <QFontDatabase> #include <QStringList> -#if defined(USE_X11) -#include "ui/gfx/x/x11_types.h" -#endif - #if defined(USE_AURA) && !defined(USE_OZONE) #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_aura.h" @@ -95,27 +92,6 @@ void GetScreenInfoFromNativeWindow(QWindow* window, content::ScreenInfo* results } // namespace QtWebEngineCore -#if defined(USE_X11) -XDisplay* GetQtXDisplay() -{ - return static_cast<XDisplay*>(GLContextHelper::getXDisplay()); -} - -namespace ui { -class DummyPlatformEventSource : public PlatformEventSource -{ -public: - DummyPlatformEventSource() { - DeviceDataManager::CreateInstance(); - } -}; - -std::unique_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() { - return base::MakeUnique<DummyPlatformEventSource>(); -} -} // namespace ui -#endif // defined(USE_X11) - namespace content { class WebContentsImpl; class WebContentsView; @@ -159,7 +135,7 @@ std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() return std::move(font_list); } -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) // content/browser/renderer_host/pepper/pepper_truetype_font_list.h void GetFontFamilies_SlowBlocking(std::vector<std::string> *font_families) { @@ -173,7 +149,7 @@ void GetFontsInFamily_SlowBlocking(const std::string &, std::vector<ppapi::proxy { QT_NOT_USED } -#endif // BUILDFLAG(ENABLE_PLUGINS) +#endif // QT_CONFIG(webengine_pepper_plugins) } // namespace content @@ -196,14 +172,3 @@ std::unique_ptr<ui::OSExchangeData::Provider> ui::OSExchangeDataProviderFactory::CreateProvider() { return nullptr; } - -#if defined(USE_OPENSSL_CERTS) -namespace net { - -scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(const X509Certificate* certificate) -{ - return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(certificate); -} - -} // namespace net -#endif diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp new file mode 100644 index 000000000..7d08d57c1 --- /dev/null +++ b/src/core/client_cert_select_controller.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "client_cert_select_controller.h" + +#include <base/bind.h> +#include <content/public/browser/client_certificate_delegate.h> +#include <net/cert/x509_certificate.h> +#include <net/ssl/client_cert_identity.h> +#include <net/ssl/ssl_cert_request_info.h> +#include <net/ssl/ssl_info.h> + +#include "type_conversion.h" + +QT_BEGIN_NAMESPACE + +using namespace QtWebEngineCore; + +ClientCertSelectController::ClientCertSelectController(net::SSLCertRequestInfo *certRequestInfo, + std::vector<std::unique_ptr<net::ClientCertIdentity>> clientCerts, + std::unique_ptr<content::ClientCertificateDelegate> delegate) + : m_clientCerts(std::move(clientCerts)) + , m_delegate(std::move(delegate)) + , m_selected(false) +{ + m_hostAndPort.setHost(QString::fromStdString(certRequestInfo->host_and_port.HostForURL())); + m_hostAndPort.setPort(certRequestInfo->host_and_port.port()); +} + +ClientCertSelectController::~ClientCertSelectController() +{ + // Continue without a client certificate, for instance if the app has not + // implemented support for client certificate selection. + if (!m_selected) + m_delegate->ContinueWithCertificate(nullptr, nullptr); +} + +#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + +void ClientCertSelectController::selectNone() +{ + if (m_selected) { + qWarning() << "ClientCertSelectController::selectNone() certicate already selected"; + return; + } + m_selected = true; + m_delegate->ContinueWithCertificate(nullptr, nullptr); +} + +void ClientCertSelectController::select(const QSslCertificate &certificate) +{ + if (m_selected) { + qWarning() << "ClientCertSelectController::select() certicate already selected"; + return; + } + QByteArray derCertificate = certificate.toDer(); + scoped_refptr<net::X509Certificate> selectedCert = + net::X509Certificate::CreateFromBytes(derCertificate.constData(), derCertificate.length()); + for (auto &certInfo : m_clientCerts) { + scoped_refptr<net::X509Certificate> cert = certInfo->certificate(); + if (cert->EqualsExcludingChain(selectedCert.get())) { + m_selected = true; + net::ClientCertIdentity::SelfOwningAcquirePrivateKey( + std::move(certInfo), + base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate, + base::Passed(std::move(m_delegate)), std::move(cert))); + return; + } + } + qWarning() << "ClientCertSelectController::select() - selected client certificate not recognized." + << " Selected certificate needs to be one of the offered"; +} + +QVector<QSslCertificate> ClientCertSelectController::certificates() const +{ + QVector<QSslCertificate> out; + for (auto &cert : m_clientCerts) { + std::vector<std::string> pem_encoded; + if (cert->certificate()->GetPEMEncodedChain(&pem_encoded)) + out.append(QSslCertificate(QByteArray::fromStdString(pem_encoded.front()))); + } + return out; +} + +#endif // !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + +QT_END_NAMESPACE diff --git a/src/core/api/qwebenginebrowsercontext_p.h b/src/core/client_cert_select_controller.h index 713ab730e..46324ee90 100644 --- a/src/core/api/qwebenginebrowsercontext_p.h +++ b/src/core/client_cert_select_controller.h @@ -37,9 +37,6 @@ ** ****************************************************************************/ -#ifndef QWEBENGINEBROWSERCONTEXT_P_H -#define QWEBENGINEBROWSERCONTEXT_P_H - // // W A R N I N G // ------------- @@ -50,34 +47,53 @@ // // We mean it. // + +#ifndef CLIENT_CERT_SELECT_CONTROLLER_H +#define CLIENT_CERT_SELECT_CONTROLLER_H + #include "qtwebenginecoreglobal_p.h" +#include <QtNetwork/qtnetwork-config.h> -#include <QObject> -#include <QSharedPointer> +#include <QtCore/QUrl> +#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) +#include <QtCore/QVector> +#include <QtNetwork/QSslCertificate> +#endif +#include <memory> + +namespace content { +class ClientCertificateDelegate; +} -namespace QtWebEngineCore { -class BrowserContextAdapter; -class BrowserContextAdapterClient; +namespace net { +class ClientCertIdentity; +class SSLCertRequestInfo; } QT_BEGIN_NAMESPACE -// This is a wrapper class for BrowserContextAdapter. BrowserContextAdapter must be destructed before WebEngineContext -// is destructed. Therefore access it via the QWebEngineBrowserContext which parent is the WebEngineContext::globalQObject. -// This guarantees the destruction together with the WebEngineContext. -class QWEBENGINE_PRIVATE_EXPORT QWebEngineBrowserContext : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT ClientCertSelectController { public: - QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QtWebEngineCore::BrowserContextAdapterClient *profile); - ~QWebEngineBrowserContext(); + ClientCertSelectController(net::SSLCertRequestInfo *certRequestInfo, + std::vector<std::unique_ptr<net::ClientCertIdentity>> clientCerts, + std::unique_ptr<content::ClientCertificateDelegate> delegate); + ~ClientCertSelectController(); - void shutdown(); + QUrl hostAndPort() const { return m_hostAndPort; } +#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + void selectNone(); + void select(const QSslCertificate &certificate); - QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextRef; + QVector<QSslCertificate> certificates() const; +#endif private: - QtWebEngineCore::BrowserContextAdapterClient *m_profile; + QUrl m_hostAndPort; + std::vector<std::unique_ptr<net::ClientCertIdentity>> m_clientCerts; + std::unique_ptr<content::ClientCertificateDelegate> m_delegate; + bool m_selected; }; QT_END_NAMESPACE -#endif // QWEBENGINEBROWSERCONTEXT_P_H +#endif // CLIENT_CERT_SELECT_CONTROLLER_H diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index cff975e61..44756bdfe 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -296,7 +296,8 @@ void ClipboardQt::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::s return; if (mimeData->hasImage() && !mimeData->formats().contains(QStringLiteral("image/png"))) types->push_back(toString16(QStringLiteral("image/png"))); - Q_FOREACH (const QString &mimeType, mimeData->formats()) + const QStringList formats = mimeData->formats(); + for (const QString &mimeType : formats) types->push_back(toString16(mimeType)); *contains_filenames = false; diff --git a/src/core/color_chooser_controller.h b/src/core/color_chooser_controller.h index c0cb05172..4c1b81a9a 100644 --- a/src/core/color_chooser_controller.h +++ b/src/core/color_chooser_controller.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef COLOR_CHOOSER_CONTROLLER_H #define COLOR_CHOOSER_CONTROLLER_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QObject> @@ -48,7 +59,7 @@ namespace QtWebEngineCore { class ColorChooserControllerPrivate; -class QWEBENGINE_EXPORT ColorChooserController : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT ColorChooserController : public QObject { Q_OBJECT public: ~ColorChooserController(); diff --git a/src/core/common/qt_ipc_logging.cpp b/src/core/common/qt_ipc_logging.cpp index f2a00b23c..83eb5a5ad 100644 --- a/src/core/common/qt_ipc_logging.cpp +++ b/src/core/common/qt_ipc_logging.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "ipc/ipc_features.h" // Generated buildflag header +#include "ipc/ipc_buildflags.h" // Generated buildflag header #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED) #define IPC_MESSAGE_MACROS_LOG_ENABLED diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index c5caa0fff..987d6442b 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -5,11 +5,10 @@ // Multiply-included file, no traditional include guard. #include "base/optional.h" -#include "media/media_features.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/webplugininfo.h" #include "ipc/ipc_message_macros.h" -#include "ppapi/features/features.h" +#include "ppapi/buildflags/buildflags.h" #include "user_script_data.h" IPC_STRUCT_TRAITS_BEGIN(UserScriptData) @@ -37,12 +36,6 @@ IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentMarkup, IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentInnerText, uint64_t /* requestId */) -IPC_MESSAGE_ROUTED1(RenderViewObserverQt_SetBackgroundColor, - uint32_t /* color */) - -IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_SetWorldId, base::Optional<uint> /* worldId */) -IPC_MESSAGE_ROUTED2(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/, uint /* worldId */) - // User scripts messages IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_AddScript, UserScriptData /* script */) @@ -74,24 +67,10 @@ IPC_MESSAGE_ROUTED2(RenderViewObserverHostQt_DidFetchDocumentInnerText, IPC_MESSAGE_ROUTED0(RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout) -IPC_MESSAGE_ROUTED1(WebChannelIPCTransportHost_SendMessage, std::vector<char> /*binaryJSON*/) - //----------------------------------------------------------------------------- // Misc messages // These are messages sent from the renderer to the browser process. -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) -// Returns whether any internal plugin supporting |mime_type| is registered and -// enabled. Does not determine whether the plugin can actually be instantiated -// (e.g. whether it has all its dependencies). -// When the returned *|is_available| is true, |additional_param_names| and -// |additional_param_values| contain the name-value pairs, if any, specified -// for the *first* non-disabled plugin found that is registered for |mime_type|. -IPC_SYNC_MESSAGE_CONTROL1_1(QtWebEngineHostMsg_IsInternalPluginAvailableForMimeType, - std::string /* mime_type */, - base::Optional<std::vector<content::WebPluginMimeType::Param>>) -#endif - // Sent by the renderer process to check whether access to web databases is // granted by content settings. IPC_SYNC_MESSAGE_CONTROL5_1(QtWebEngineHostMsg_AllowDatabase, diff --git a/src/core/compositor.cpp b/src/core/compositor.cpp new file mode 100644 index 000000000..5dd053718 --- /dev/null +++ b/src/core/compositor.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "compositor.h" + +#include "delegated_frame_node.h" + +#include <components/viz/common/resources/returned_resource.h> +#include <content/public/browser/browser_thread.h> +#include <services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h> + +namespace QtWebEngineCore { + +Compositor::Compositor() + : m_chromiumCompositorData(new ChromiumCompositorData) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + base::SingleThreadTaskRunner *taskRunner = + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI).get(); + m_beginFrameSource = + std::make_unique<viz::DelayBasedBeginFrameSource>( + std::make_unique<viz::DelayBasedTimeSource>(taskRunner), + viz::BeginFrameSource::kNotRestartableId); +} + +Compositor::~Compositor() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} + +void Compositor::setViewDelegate(RenderWidgetHostViewQtDelegate *viewDelegate) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + m_viewDelegate = viewDelegate; +} + +void Compositor::setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (m_frameSinkClient == frameSinkClient) + return; + + // Accumulated resources belong to the old RendererCompositorFrameSink and + // should not be returned. + // + // TODO(juvaldma): Can there be a pending frame from the old client? + m_resourcesToRelease.clear(); + m_frameSinkClient = frameSinkClient; +} + +void Compositor::setNeedsBeginFrames(bool needsBeginFrames) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (m_needsBeginFrames == needsBeginFrames) + return; + + if (needsBeginFrames) + m_beginFrameSource->AddObserver(this); + else + m_beginFrameSource->RemoveObserver(this); + + m_needsBeginFrames = needsBeginFrames; +} + +void Compositor::submitFrame(viz::CompositorFrame frame) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(!m_havePendingFrame); + + m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor; + m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); + m_chromiumCompositorData->frameData = std::move(frame); + m_havePendingFrame = true; + + // Tell viewDelegate to call updatePaintNode() soon. + m_viewDelegate->update(); +} + +QSGNode *Compositor::updatePaintNode(QSGNode *oldNode) +{ + // DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // + // This might be called from a Qt Quick render thread, but the UI thread + // will still be blocked for the duration of this call. + + DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode); + if (!frameNode) + frameNode = new DelegatedFrameNode; + + frameNode->commit(m_chromiumCompositorData.data(), &m_resourcesToRelease, m_viewDelegate); + + if (m_havePendingFrame) { + m_havePendingFrame = false; + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(&Compositor::notifyFrameCommitted, m_weakPtrFactory.GetWeakPtr())); + } + if (m_chromiumCompositorData->frameData.metadata.request_presentation_feedback) + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(&Compositor::sendPresentationFeedback, m_weakPtrFactory.GetWeakPtr(), m_chromiumCompositorData->frameData.metadata.frame_token)); + + return frameNode; +} + +void Compositor::notifyFrameCommitted() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + m_beginFrameSource->DidFinishFrame(this); + if (m_frameSinkClient) + m_frameSinkClient->DidReceiveCompositorFrameAck(m_resourcesToRelease); + m_resourcesToRelease.clear(); +} + +void Compositor::sendPresentationFeedback(uint frame_token) +{ + gfx::PresentationFeedback dummyFeedback(base::TimeTicks::Now(), base::TimeDelta(), gfx::PresentationFeedback::Flags::kVSync); + m_frameSinkClient->DidPresentCompositorFrame(frame_token, dummyFeedback); +} + +bool Compositor::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval); + if (m_frameSinkClient) + m_frameSinkClient->OnBeginFrame(args); + + return true; +} + +void Compositor::OnBeginFrameSourcePausedChanged(bool) +{ + // Ignored for now. If the begin frame source is paused, the renderer + // doesn't need to be informed about it and will just not receive more + // begin frames. +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor.h b/src/core/compositor.h new file mode 100644 index 000000000..4852d0590 --- /dev/null +++ b/src/core/compositor.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 COMPOSITOR_H +#define COMPOSITOR_H + +#include <base/memory/weak_ptr.h> +#include <components/viz/common/frame_sinks/begin_frame_source.h> + +#include <QtCore/qglobal.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE +class QSGNode; +QT_END_NAMESPACE + +namespace viz { +class CompositorFrame; +struct ReturnedResource; +namespace mojom { +class CompositorFrameSinkClient; +} // namespace mojom +} // namespace viz + +namespace QtWebEngineCore { + +class RenderWidgetHostViewQtDelegate; +class ChromiumCompositorData; + +// Receives viz::CompositorFrames from child compositors and provides QSGNodes +// to the Qt Quick renderer. +// +// The life cycle of a frame: +// +// Step 1. A new CompositorFrame is received from child compositors and handed +// off to submitFrame(). The new frame will start off in a pending state. +// +// Step 2. Once the new frame is ready to be rendered, Compositor will call +// update() on the delegate. +// +// Step 3. Once the delegate is ready to render, updatePaintNode() should be +// called to receive the scene graph for the new frame. This call will commit +// the pending frame. Until the next frame is ready, all subsequent calls to +// updatePaintNode() will keep using this same committed frame. +// +// Step 4. The Compositor will return unneeded resources back to the child +// compositors. Go to step 1. +class Compositor final : private viz::BeginFrameObserverBase +{ +public: + explicit Compositor(); + ~Compositor() override; + + void setViewDelegate(RenderWidgetHostViewQtDelegate *viewDelegate); + void setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient); + void setNeedsBeginFrames(bool needsBeginFrames); + + void submitFrame(viz::CompositorFrame frame); + + QSGNode *updatePaintNode(QSGNode *oldNode); + +private: + void notifyFrameCommitted(); + void sendPresentationFeedback(uint frame_token); + + // viz::BeginFrameObserverBase + bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args) override; + void OnBeginFrameSourcePausedChanged(bool paused) override; + + std::vector<viz::ReturnedResource> m_resourcesToRelease; + QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; + RenderWidgetHostViewQtDelegate *m_viewDelegate = nullptr; + std::unique_ptr<viz::SyntheticBeginFrameSource> m_beginFrameSource; + viz::mojom::CompositorFrameSinkClient *m_frameSinkClient = nullptr; + bool m_havePendingFrame = false; + bool m_needsBeginFrames = false; + + base::WeakPtrFactory<Compositor> m_weakPtrFactory{this}; + + DISALLOW_COPY_AND_ASSIGN(Compositor); +}; + +} // namespace QtWebEngineCore + +#endif // !COMPOSITOR_H diff --git a/src/core/config/common.pri b/src/core/config/common.pri index 3441d9623..6b79a1f99 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -1,13 +1,19 @@ # Shared configuration for all our supported platforms +include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) +QT_FOR_CONFIG += webenginecore gn_args += \ use_qt=true \ is_component_build=false \ is_shared=true \ + enable_message_center=false \ + enable_mus=false \ enable_nacl=false \ enable_remoting=false \ enable_reporting=false \ enable_web_speech=false \ + enable_widevine=true \ + has_native_accessibility=false \ use_allocator_shim=false \ use_allocator=\"none\" \ v8_use_external_startup_data=false \ @@ -17,8 +23,7 @@ gn_args += \ !win32: gn_args += \ use_jumbo_build=true \ - jumbo_file_merge_limit=8 \ - jumbo_build_excluded="[\"browser\",\"renderer\"]" + jumbo_file_merge_limit=8 qtConfig(webengine-printing-and-pdf) { gn_args += enable_basic_printing=true enable_print_preview=true @@ -29,9 +34,9 @@ qtConfig(webengine-printing-and-pdf) { } qtConfig(webengine-pepper-plugins) { - gn_args += enable_plugins=true enable_widevine=true + gn_args += enable_plugins=true } else { - gn_args += enable_plugins=false enable_widevine=false + gn_args += enable_plugins=false } qtConfig(webengine-spellchecker) { @@ -94,4 +99,10 @@ qtConfig(webengine-v8-snapshot) { gn_args += v8_use_snapshot=false } +qtConfig(webengine-kerberos) { + gn_args += use_kerberos=true +} else { + gn_args += use_kerberos=false +} + !msvc: gn_args += enable_iterator_debugging=false diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri deleted file mode 100644 index 70f1cf81e..000000000 --- a/src/core/config/desktop_linux.pri +++ /dev/null @@ -1,8 +0,0 @@ -include(linux.pri) - -gn_args += \ - use_sysroot=false \ - enable_session_service=false \ - toolkit_views=false - -!use_gold_linker: gn_args += use_gold=false diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri deleted file mode 100644 index 8d9f09deb..000000000 --- a/src/core/config/embedded_linux.pri +++ /dev/null @@ -1,13 +0,0 @@ -include(linux.pri) - -gn_args += \ - is_desktop_linux=false \ - use_gold=false \ - use_ozone=true \ - use_sysroot=false \ - enable_session_service=false \ - ozone_auto_platforms=false \ - ozone_platform_headless=true \ - ozone_platform_external=true \ - ozone_platform=\"qt\" \ - toolkit_views=false diff --git a/src/core/config/embedded_qnx.pri b/src/core/config/embedded_qnx.pri deleted file mode 100644 index f24888776..000000000 --- a/src/core/config/embedded_qnx.pri +++ /dev/null @@ -1,10 +0,0 @@ -GYP_ARGS += "-D qt_os=\"embedded_qnx\" -I config/embedded_qnx.gypi" - -include(common.pri) - -GYP_CONFIG += \ - disable_nacl=1 \ - enable_webrtc=0 \ - use_ash=0 \ - use_aura=1 \ - use_ozone=1 \ diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri index 4ade28271..eb8bb7bb0 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -1,17 +1,32 @@ include(common.pri) -include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) -QT_FOR_CONFIG += gui-private webengine-private +QT_FOR_CONFIG += gui-private webenginecore-private gn_args += \ use_cups=false \ use_gio=false \ use_gnome_keyring=false \ - use_kerberos=false \ linux_use_bundled_binutils=false \ use_udev=true \ - use_bundled_fontconfig=false + use_bundled_fontconfig=false \ + use_sysroot=false \ + enable_session_service=false \ + toolkit_views=false \ + use_ozone=true \ + ozone_auto_platforms=false \ + ozone_platform_headless=false \ + ozone_platform_external=true \ + ozone_platform=\"qt\" + +qtConfig(webengine-embedded-build) { + gn_args += is_desktop_linux=false + gn_args += use_gold=false +} else { + !use_gold_linker: gn_args += use_gold=false +} -gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): gn_args += no_delete_null_pointer_checks=true +qtConfig(webengine-system-x11): hasX11Dependencies() { + gn_args += ozone_platform_x11=true +} clang { clang_full_path = $$which($${QMAKE_CXX}) diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index 2d820c889..4426901cf 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -24,11 +24,11 @@ system("$${QMAKE_CLANG_PATH} --version") 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}\" \ + mac_views_browser=false \ toolkit_views=false \ use_external_popup_menu=false diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index 5aa511da3..3b42a0b9a 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -3,7 +3,6 @@ include(common.pri) gn_args += \ is_clang=false \ use_sysroot=false \ - use_kerberos=true \ enable_session_service=false \ ninja_use_custom_environment_files=false \ is_multi_dll_chrome=false \ diff --git a/src/core/configure.json b/src/core/configure.json new file mode 100644 index 000000000..3aba2d55a --- /dev/null +++ b/src/core/configure.json @@ -0,0 +1,822 @@ +{ + "module": "webenginecore", + "depends": [ + "core-private", + "gui-private", + "printsupport" + ], + "testDir": "../../config.tests", + "commandline": { + "options": { + "webengine-alsa": "boolean", + "webengine-embedded-build": "boolean", + "webengine-icu": { "type": "enum", "name": "webengine-system-icu", "values": { "system": "yes", "qt": "no" } }, + "webengine-ffmpeg": { "type": "enum", "name": "webengine-system-ffmpeg", "values": { "system": "yes", "qt": "no" } }, + "webengine-opus": { "type": "enum", "name": "webengine-system-opus", "values": { "system": "yes", "qt": "no" } }, + "webengine-webp": { "type": "enum", "name": "webengine-system-libwebp", "values": { "system": "yes", "qt": "no" } }, + "webengine-pepper-plugins": "boolean", + "webengine-printing-and-pdf": "boolean", + "webengine-proprietary-codecs": "boolean", + "webengine-pulseaudio": "boolean", + "webengine-spellchecker": "boolean", + "webengine-native-spellchecker": "boolean", + "webengine-webrtc": "boolean", + "webengine-geolocation": "boolean", + "webengine-v8-snapshot": "boolean", + "webengine-webchannel": "boolean", + "webengine-kerberos": "boolean", + "alsa": { "type": "boolean", "name": "webengine-alsa" }, + "pulseaudio": { "type": "boolean", "name": "webengine-pulseaudio" }, + "ffmpeg": { "type": "enum", "name": "webengine-system-ffmpeg", "values": { "system": "yes", "qt": "no" } }, + "opus": { "type": "enum", "name": "webengine-system-opus", "values": { "system": "yes", "qt": "no" } }, + "webp": { "type": "enum", "name": "webengine-system-libwebp", "values": { "system": "yes", "qt": "no" } }, + "pepper-plugins": { "type": "boolean", "name": "webengine-pepper-plugins" }, + "printing-and-pdf": { "type": "boolean", "name": "webengine-printing-and-pdf" }, + "proprietary-codecs": { "type": "boolean", "name": "webengine-proprietary-codecs" }, + "spellchecker": { "type": "boolean", "name": "webengine-spellchecker" }, + "webrtc": { "type": "boolean", "name": "webengine-webrtc" } + } + }, + + "libraries": { + "webengine-dbus": { + "label": "d-bus", + "sources": [ + { "type": "pkgConfig", "args": "dbus-1" } + ] + }, + "webengine-fontconfig": { + "label": "fontconfig", + "sources": [ + { "type": "pkgConfig", "args": "fontconfig" } + ] + }, + "webengine-libdrm": { + "label": "libdrm", + "sources": [ + { "type": "pkgConfig", "args": "libdrm" } + ] + }, + "webengine-xcomposite": { + "label": "xcomposite", + "sources": [ + { "type": "pkgConfig", "args": "xcomposite" } + ] + }, + "webengine-xcursor": { + "label": "xcursor", + "sources": [ + { "type": "pkgConfig", "args": "xcursor" } + ] + }, + "webengine-xi": { + "label": "xi", + "sources": [ + { "type": "pkgConfig", "args": "xi" } + ] + }, + "webengine-xrandr": { + "label": "xrandr", + "sources": [ + { "type": "pkgConfig", "args": "xrandr" } + ] + }, + "webengine-xtst": { + "label": "xtst", + "sources": [ + { "type": "pkgConfig", "args": "xtst" } + ] + }, + "webengine-harfbuzz": { + "label": "harfbuzz >= 1.4.2", + "sources": [ + { "type": "pkgConfig", "args": "harfbuzz >= 1.4.2" } + ] + }, + "webengine-glib": { + "label": "glib-2.0 >= 2.32.0", + "sources": [ + { "type": "pkgConfig", "args": "glib-2.0 >= 2.32.0" } + ] + }, + "webengine-zlib": { + "label": "zlib", + "sources": [ + { "type": "pkgConfig", "args": "zlib" } + ] + }, + "webengine-minizip": { + "label": "minizip", + "sources": [ + { "type": "pkgConfig", "args": "minizip" } + ] + }, + "webengine-libevent": { + "label": "libevent", + "sources": [ + { "type": "pkgConfig", "args": "libevent" } + ] + }, + "webengine-libxml2": { + "label": "libxml2 and libxslt", + "sources": [ + { "type": "pkgConfig", "args": "libxml-2.0 libxslt" } + ] + }, + "webengine-jsoncpp": { + "label": "jsoncpp", + "sources": [ + { "type": "pkgConfig", "args": "jsoncpp" } + ] + }, + "webengine-protobuf": { + "label": "protobuf", + "sources": [ + { "type": "pkgConfig", "args": "protobuf" } + ] + }, + "webengine-poppler-cpp": { + "label": "poppler-cpp", + "sources": [ + { "type": "pkgConfig", "args": "poppler-cpp" } + ] + }, + "pulseaudio": { + "label": "pulseaudio >= 0.9.10", + "sources": [ + { "type": "pkgConfig", "args": "libpulse >= 0.9.10 libpulse-mainloop-glib" } + ] + }, + "webengine-icu": { + "label": "icu >= 53", + "sources": [ + { "type": "pkgConfig", "args": "icu-uc >= 53 icu-i18n >= 53" } + ] + }, + "webengine-ffmpeg": { + "label": "libavcodec libavformat libavutil", + "sources": [ + { "type": "pkgConfig", "args": "libavcodec libavformat libavutil" } + ] + }, + "webengine-opus": { + "label": "opus", + "sources": [ + { "type": "pkgConfig", "args": "opus" } + ] + }, + "webengine-webp": { + "label": "libwebp, libwebpmux and libwebpdemux", + "sources": [ + { "type": "pkgConfig", "args": "libwebp libwebpmux libwebpdemux" } + ] + }, + "webengine-nss": { + "label": "nss >= 3.26", + "sources": [ + { "type": "pkgConfig", "args": "nss >= 3.26" } + ] + }, + "webengine-png": { + "label": "libpng >= 1.6.0", + "sources": [ + { "type": "pkgConfig", "args": "libpng >= 1.6.0" } + ] + }, + "webengine-jpeglib": { + "label": "compatible jpeglib", + "type": "compile", + "test": { + "head": [ + "#include <cstdio>", + "#include <cstring>", + "extern \"C\" {", + " #include <jpeglib.h>", + "}" + ], + "main": [ + "JDIMENSION dummy;", + "jpeg_crop_scanline(nullptr, &dummy, &dummy);", + "jpeg_skip_scanlines(nullptr, dummy);" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "libjpeg" }, + "-ljpeg" + ] + }, + "webengine-lcms2": { + "label": "lcms2", + "sources": [ + { "type": "pkgConfig", "args": "lcms2" } + ] + }, + "webengine-freetype": { + "label": "freetype >= 2.4.2", + "test": { + "head": [ + "#include <ft2build.h>", + "#include FT_FREETYPE_H", + "#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20402)", + "# error This version of freetype is too old.", + "#endif" + ], + "main": [ + "FT_Face ft_face = 0;", + "FT_Reference_Face(ft_face);" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "freetype2" } + ] + }, + "webengine-x11" : { + "label" : "x11", + "sources": [ + { "type": "pkgConfig", "args": "x11" } + ] + } + }, + "tests" : { + "webengine-alsa": { + "label": "alsa", + "test": "alsa", + "type": "compile" + }, + "webengine-host-compiler": { + "label": "host compiler", + "test": "hostcompiler", + "host": "true", + "type": "compile" + }, + "webengine-khr": { + "label": "khr", + "test": "khr", + "type": "compile" + }, + "webengine-libvpx": { + "label": "libvpx", + "test": "libvpx", + "type": "compile" + }, + "webengine-snappy": { + "label": "snappy", + "test": "snappy", + "type": "compile" + }, + "webengine-winversion": { + "label": "winversion", + "test": "winversion", + "type": "compile" + }, + "webengine-protoc": { + "label": "protoc", + "type": "detectProtoc" + }, + "webengine-python2": { + "label": "python2", + "type": "detectPython2", + "log": "location" + }, + "webengine-host-pkg-config": { + "label": "host pkg-config", + "type": "detectHostPkgConfig", + "log": "path" + }, + "webengine-gperf": { + "label": "gperf", + "type": "detectGperf" + }, + "webengine-bison": { + "label": "bison", + "type": "detectBison" + }, + "webengine-flex": { + "label": "flex", + "type": "detectFlex" + }, + "webengine-ninja": { + "label": "system ninja", + "type": "detectNinja" + }, + "webengine-gn": { + "label": "system gn", + "type": "detectGn" + }, + "webengine-embedded-build": { + "label": "embedded", + "type": "embedded" + }, + "webengine-re2": { + "label": "re2", + "test": "re2", + "type": "compile" + }, + "webengine-glibc": { + "label": "glibc > 2.16", + "type": "detectGlibc" + }, + "webengine-libxml2-compatible": { + "label" : "compatible system libxml2", + "test" : "xml2", + "type": "compile" + }, + "webengine-sanitizer": { + "label" : "sanitizer support", + "type": "isSanitizerSupported" + }, + "webengine-win-compiler64": { + "label": "64bit compiler", + "type": "isWindowsHostCompiler64" + } + }, + + "features": { + "webengine-system-fontconfig": { + "label": "fontconfig", + "condition": "libs.webengine-fontconfig", + "output": [ "privateFeature" ] + }, + "webengine-system-dbus": { + "label": "dbus", + "condition": "libs.webengine-dbus", + "output": [ "privateFeature" ] + }, + "webengine-system-libdrm": { + "label": "libdrm", + "condition": "libs.webengine-libdrm", + "output": [ "privateFeature" ] + }, + "webengine-system-xcomposite": { + "label": "xcomposite", + "condition": "libs.webengine-xcomposite", + "output": [ "privateFeature" ] + }, + "webengine-system-xcursor": { + "label": "xcursor", + "condition": "libs.webengine-xcursor", + "output": [ "privateFeature" ] + }, + "webengine-system-xi": { + "label": "xi", + "condition": "libs.webengine-xi", + "output": [ "privateFeature" ] + }, + "webengine-system-xrandr": { + "label": "xrandr", + "condition": "libs.webengine-xrandr", + "output": [ "privateFeature" ] + }, + "webengine-system-xtst": { + "label": "xtst", + "condition": "libs.webengine-xtst", + "output": [ "privateFeature" ] + }, + "webengine-system-harfbuzz": { + "label": "harfbuzz", + "condition": "config.unix && features.system-harfbuzz && libs.webengine-harfbuzz", + "output": [ "privateFeature" ] + }, + "webengine-system-glib" : { + "label": "glib", + "condition": "config.unix && libs.webengine-glib", + "output": [ "privateFeature" ] + }, + "webengine-system-minizip" : { + "label": "minizip", + "condition": "config.unix && libs.webengine-minizip", + "output": [ "privateFeature" ] + }, + "webengine-system-zlib" : { + "label": "zlib", + "condition": "config.unix && features.system-zlib && libs.webengine-zlib", + "output": [ "privateFeature" ] + }, + "webengine-system-libevent" : { + "label": "libevent", + "condition": "config.unix && libs.webengine-libevent", + "output": [ "privateFeature" ] + }, + "webengine-system-jsoncpp" : { + "label": "jsoncpp", + "condition": "config.unix && libs.webengine-jsoncpp", + "output": [ "privateFeature" ] + }, + "webengine-system-protobuf" : { + "label": "protobuf", + "condition": "config.unix && libs.webengine-protobuf && tests.webengine-protoc", + "output": [ "privateFeature" ] + }, + "webengine-system-png" : { + "label": "png", + "condition": "config.unix && features.system-png && libs.webengine-png", + "output": [ "privateFeature" ] + }, + "webengine-system-jpeg" : { + "label": "JPEG", + "condition": "config.unix && features.system-jpeg && libs.webengine-jpeglib", + "output": [ "privateFeature" ] + }, + "webengine-python2": { + "label": "python2", + "condition": "tests.webengine-python2", + "output": [ + "privateFeature", + { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.webengine-python2.location" } + ] + }, + "webengine-host-pkg-config": { + "label": "host-pkg-config", + "condition": "config.unix && tests.webengine-host-pkg-config", + "output": [ + "privateFeature", + { "type": "varAssign", "name": "QMAKE_PKG_CONFIG_HOST", "value": "tests.webengine-host-pkg-config.path" } + ] + }, + "webengine-gperf": { + "label": "gperf", + "condition": "tests.webengine-gperf", + "output": [ "privateFeature" ] + }, + "webengine-bison": { + "label": "bison", + "condition": "tests.webengine-bison", + "output": [ "privateFeature" ] + }, + "webengine-flex": { + "label": "flex", + "condition": "tests.webengine-flex", + "output": [ "privateFeature" ] + }, + "webengine-embedded-build": { + "label": "Embedded build", + "purpose": "Enables the embedded build configuration.", + "section": "WebEngine", + "condition": "config.unix", + "autoDetect": "tests.webengine-embedded-build", + "output": [ "privateFeature" ] + }, + "webengine-alsa": { + "label": "Use ALSA", + "condition": "config.unix && tests.webengine-alsa", + "output": [ "privateFeature" ] + }, + "webengine-v8-snapshot": { + "label" : "Use v8 snapshot", + "purpose": "Enables the v8 snapshot, for fast v8 context creation", + "output": [ "privateFeature" ] + }, + "webengine-v8-snapshot-support": { + "label" : "Building v8 snapshot supported", + "autoDetect": "features.webengine-v8-snapshot", + "condition": "!config.unix || !features.cross_compile || arch.arm64 || tests.webengine-host-compiler", + "output": [ "privateFeature" ] + }, + "webengine-system-khr" : { + "label": "khr", + "condition": "config.unix && tests.webengine-khr", + "output": [ "privateFeature" ] + }, + "webengine-system-libvpx" : { + "label": "libvpx", + "condition": "config.unix && tests.webengine-libvpx", + "output": [ "privateFeature" ] + }, + "webengine-system-snappy" : { + "label": "snappy", + "condition": "config.unix && tests.webengine-snappy", + "output": [ "privateFeature" ] + }, + "webengine-winversion" : { + "label": "winversion", + "condition": "config.win32 && tests.webengine-winversion", + "output": [ "privateFeature" ] + }, + "webengine-geolocation": { + "label": "Geolocation", + "condition": "module.positioning", + "output": [ "publicFeature" ] + }, + "webengine-pulseaudio": { + "label": "Use PulseAudio", + "autoDetect": "config.unix", + "condition": "libs.pulseaudio", + "output": [ "privateFeature" ] + }, + "webengine-pepper-plugins": { + "label": "Pepper Plugins", + "purpose": "Enables use of Pepper Flash plugins.", + "section": "WebEngine", + "autoDetect": "!features.webengine-embedded-build", + "output": [ "privateFeature" ] + }, + "webengine-printing-and-pdf": { + "label": "Printing and PDF", + "purpose": "Provides printing and output to PDF.", + "section": "WebEngine", + "condition": "module.printsupport && features.printer", + "autoDetect": "!features.webengine-embedded-build", + "output": [ "privateFeature" ] + }, + "webengine-webchannel": { + "label": "WebChannel support", + "purpose": "Provides QtWebChannel integration.", + "section": "WebEngine", + "condition": "module.webchannel", + "output": [ "publicFeature" ] + }, + "webengine-proprietary-codecs": { + "label": "Proprietary Codecs", + "purpose": "Enables the use of proprietary codecs such as h.264/h.265 and MP3.", + "section": "WebEngine", + "autoDetect": false, + "output": [ "privateFeature" ] + }, + "webengine-kerberos": { + "label": "Kerberos Authentication", + "purpose": "Enables Kerberos Authentication Support", + "autoDetect": "config.win32", + "section": "WebEngine", + "output": [ "privateFeature" ] + }, + "webengine-spellchecker": { + "label": "Spellchecker", + "purpose": "Provides a spellchecker.", + "section": "WebEngine", + "output": [ "publicFeature" ] + }, + "webengine-native-spellchecker": { + "label": "Native Spellchecker", + "purpose": "Use the system's native spellchecking engine.", + "section": "WebEngine", + "autoDetect": false, + "condition": "config.macos && features.webengine-spellchecker", + "output": [ "publicFeature" ] + }, + "webengine-ui-delegates": { + "label": "UI Delegates", + "output": [ "privateFeature" ] + }, + "webengine-testsupport": { + "label": "Test Support", + "autoDetect": "features.private_tests || call.isTestsInBuildParts", + "output": [ "privateFeature" ] + }, + "webengine-webrtc": { + "label": "WebRTC", + "purpose": "Provides WebRTC support.", + "section": "WebEngine", + "autoDetect": "!features.webengine-embedded-build", + "output": [ "privateFeature" ] + }, + "webengine-system-nss": { + "label": "nss", + "condition": "config.unix && !config.darwin && libs.webengine-nss", + "output": [ "privateFeature" ] + }, + "webengine-system-libwebp": { + "label": "libwebp, libwebpmux and libwebpdemux", + "autoDetect": "config.unix", + "condition": "libs.webengine-webp", + "output": [ "privateFeature" ] + }, + "webengine-system-opus": { + "label": "opus", + "autoDetect": "config.unix", + "condition": "libs.webengine-opus", + "output": [ "privateFeature" ] + }, + "webengine-system-ffmpeg": { + "label": "ffmpeg", + "autoDetect": false, + "condition": "libs.webengine-ffmpeg && features.webengine-system-opus && features.webengine-system-libwebp", + "output": [ "privateFeature" ] + }, + "webengine-system-icu": { + "label": "icu", + "autoDetect": false, + "condition": "libs.webengine-icu", + "output": [ "privateFeature" ] + }, + "webengine-system-re2": { + "label": "re2", + "autoDetect": "config.unix", + "condition": "tests.webengine-re2", + "output": [ "privateFeature" ] + }, + "webengine-system-ninja": { + "label": "Use System Ninja", + "condition": "tests.webengine-ninja", + "output": [ "privateFeature" ] + }, + "webengine-system-gn": { + "label": "Use System Gn", + "autoDetect": false, + "condition": "tests.webengine-gn", + "output": [ "privateFeature" ] + }, + "webengine-system-glibc": { + "label": "glibc", + "condition": "config.linux && tests.webengine-glibc", + "output": [ "privateFeature" ] + }, + "webengine-system-libxml2": { + "label": "libxml2 and libxslt", + "condition": "config.unix + && libs.webengine-libxml2 + && tests.webengine-libxml2-compatible", + "output": [ "privateFeature" ] + }, + "webengine-system-lcms2" : { + "label": "lcms2", + "autoDetect": "features.webengine-printing-and-pdf", + "condition": "config.unix && libs.webengine-lcms2", + "output": [ "privateFeature" ] + }, + "webengine-system-freetype" : { + "label": "freetype", + "condition": "config.unix && features.system-freetype && libs.webengine-freetype", + "output": [ "privateFeature" ] + }, + "webengine-system-x11" : { + "label": "x11", + "condition": "config.unix && libs.webengine-x11", + "output": [ "privateFeature" ] + }, + "webengine-sanitizer" : { + "label": "Sanitizer", + "autoDetect": "config.sanitizer && tests.webengine-sanitizer", + "condition": "config.sanitizer", + "output": [ "privateFeature" ] + }, + "webengine-poppler-cpp": { + "label": "poppler-cpp", + "autoDetect": "config.unix", + "condition": "libs.webengine-poppler-cpp", + "output": [ "privateFeature" ] + }, + "webengine-win-compiler64": { + "label": "64bit compiler", + "condition": "config.win32 && tests.webengine-win-compiler64", + "type": "isWindowsHostCompiler64", + "output": [ "privateFeature" ] + } + }, + + "report": [ + { + "type": "warning", + "condition": "!features.webengine-python2", + "message": "Python version 2 (2.7.5 or later) is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-gperf", + "message": "gperf is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-bison", + "message": "bison is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-flex", + "message": "flex is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "config.sanitizer && !tests.webengine-sanitizer && !features.webengine-sanitizer", + "message": "Qt WebEngine cannot be built with the chosen sanitizer configuration. Check config.log for details or use -feature-webengine-sanitizer to force the build." + }, + { + "type": "warning", + "condition": "config.unix && !features.webengine-host-pkg-config", + "message": "host pkg-config not found" + }, + { + "type": "warning", + "condition": "config.win32 && !features.webengine-win-compiler64", + "message": "64-bit cross-building or native toolchain is required to build QtWebEngine." + } + ], + + "summary": [ + { + "section": "Qt WebEngine", + "entries": [ + "webengine-embedded-build", + "webengine-pepper-plugins", + "webengine-printing-and-pdf", + "webengine-proprietary-codecs", + "webengine-spellchecker", + "webengine-native-spellchecker", + "webengine-webrtc", + "webengine-system-ninja", + "webengine-geolocation", + "webengine-webchannel", + "webengine-v8-snapshot", + "webengine-kerberos", + { + "type": "feature", + "args": "webengine-v8-snapshot-support", + "condition": "config.unix && config.cross_compile && features.webengine-v8-snapshot" + }, + { + "type": "feature", + "args": "webengine-alsa", + "condition": "config.unix" + }, + { + "type": "feature", + "args": "webengine-pulseaudio", + "condition": "config.unix" + }, + { + "type": "feature", + "args": "webengine-sanitizer", + "condition": "config.sanitizer" + }, + { + "message": "macOS version", + "type": "macosToolchainVersion", + "args": "macosVersion", + "condition": "config.macos" + }, + { + "message": "Xcode version", + "type": "macosToolchainVersion", + "args": "xcodeVersion", + "condition": "config.macos" + }, + { + "message": "Clang version", + "type": "macosToolchainVersion", + "args": "clangVersion", + "condition": "config.macos" + }, + { + "message": "macOS SDK version", + "type": "macosToolchainVersion", + "args": "sdkVersion", + "condition": "config.macos" + }, + { + "message": "macOS minimum deployment target", + "type": "macosToolchainVersion", + "args": "deploymentTarget", + "condition": "config.macos" + }, + { + "section": "Optional system libraries used", + "condition": "config.unix", + "entries": [ + "webengine-system-re2", + "webengine-system-icu", + "webengine-system-libwebp", + "webengine-system-opus", + "webengine-system-ffmpeg", + "webengine-system-libvpx", + "webengine-system-snappy", + "webengine-system-glib", + "webengine-system-zlib", + "webengine-system-minizip", + "webengine-system-libevent", + "webengine-system-jsoncpp", + "webengine-system-protobuf", + "webengine-system-libxml2", + "webengine-system-lcms2", + "webengine-system-png", + "webengine-system-jpeg", + "webengine-system-harfbuzz", + "webengine-system-freetype", + "webengine-system-x11" + ] + }, + { + "section": "Required system libraries", + "condition": "config.unix && !config.macos", + "entries": [ + "webengine-system-fontconfig", + "webengine-system-dbus", + "webengine-system-nss", + "webengine-system-khr", + "webengine-system-glibc" + ] + }, + { + "section": "Required system libraries for qpa-xcb", + "condition": "config.unix && !config.macos", + "entries": [ + "webengine-system-libdrm", + "webengine-system-xcomposite", + "webengine-system-xcursor", + "webengine-system-xi", + "webengine-system-xrandr", + "webengine-system-xtst" + ] + } + ] + } + ] +} diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index a1fc7116e..0a51cc261 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -41,18 +41,13 @@ #include "base/json/json_reader.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/threading/thread_restrictions.h" -#include "components/spellcheck/spellcheck_build_features.h" -#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "base/strings/utf_string_conversions.h" +#if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" -#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) -#include "components/spellcheck/browser/spellcheck_message_filter_platform.h" -#endif #endif +#include "components/network_hints/browser/network_hints_message_filter.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/common/url_schemes.h" -#include "content/public/browser/browser_main_parts.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" @@ -61,71 +56,83 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_dispatcher_host.h" +#include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" +#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" #include "content/public/common/url_constants.h" -#include "device/geolocation/public/cpp/location_provider.h" +#include "media/media_buildflags.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "printing/features/features.h" +#include "printing/buildflags/buildflags.h" #include "net/ssl/client_cert_identity.h" -#include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/service.h" #include "services/proxy_resolver/proxy_resolver_service.h" -#include "third_party/WebKit/public/platform/modules/insecure_input/insecure_input_service.mojom.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/sandbox/switches.h" +#include "third_party/blink/public/platform/modules/insecure_input/insecure_input_service.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" -#include "ui/display/screen.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gpu_timing.h" +#include "url/url_util_qt.h" #include "qtwebengine/grit/qt_webengine_resources.h" -#include "browser_context_adapter.h" -#include "browser_context_qt.h" +#include "profile_adapter.h" +#include "browser_main_parts_qt.h" #include "browser_message_filter_qt.h" #include "certificate_error_controller.h" #include "certificate_error_controller_p.h" -#include "desktop_screen_qt.h" +#include "client_cert_select_controller.h" #include "devtools_manager_delegate_qt.h" +#include "login_delegate_qt.h" #include "media_capture_devices_dispatcher.h" #include "net/network_delegate_qt.h" #include "net/qrc_protocol_handler_qt.h" #include "net/url_request_context_getter_qt.h" -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) #include "printing/printing_message_filter_qt.h" -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif +#include "profile_qt.h" #include "quota_permission_context_qt.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.h" #include "renderer_host/user_resource_controller_host.h" +#include "service/service_qt.h" #include "type_conversion.h" #include "web_contents_delegate_qt.h" #include "web_engine_context.h" #include "web_engine_library_info.h" -#if defined(Q_OS_WIN) -#include "ui/display/win/screen_win.h" -#endif - #if defined(Q_OS_LINUX) #include "global_descriptors_qt.h" #include "ui/base/resource/resource_bundle.h" #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if defined(USE_NSS_CERTS) +#include "net/ssl/client_cert_store_nss.h" +#endif + +#if defined(OS_WIN) +#include "net/ssl/client_cert_store_win.h" +#endif + +#if defined(OS_MACOSX) +#include "net/ssl/client_cert_store_mac.h" +#endif + +#if QT_CONFIG(webengine_pepper_plugins) #include "content/public/browser/browser_ppapi_host.h" #include "ppapi/host/ppapi_host.h" #include "renderer_host/pepper/pepper_host_factory_qt.h" #endif -#if defined(QT_USE_POSITIONING) +#if QT_CONFIG(webengine_geolocation) #include "location_provider_qt.h" #endif @@ -142,157 +149,6 @@ QT_END_NAMESPACE namespace QtWebEngineCore { -namespace { - -ContentBrowserClientQt* gBrowserClient = 0; // Owned by ContentMainDelegateQt. - -// Return a timeout suitable for the glib loop, -1 to block forever, -// 0 to return right away, or a timeout in milliseconds from now. -int GetTimeIntervalMilliseconds(const base::TimeTicks& from) { - if (from.is_null()) - return -1; - - // Be careful here. TimeDelta has a precision of microseconds, but we want a - // value in milliseconds. If there are 5.5ms left, should the delay be 5 or - // 6? It should be 6 to avoid executing delayed work too early. - int delay = static_cast<int>( - ceil((from - base::TimeTicks::Now()).InMillisecondsF())); - - // If this value is negative, then we need to run delayed work soon. - return delay < 0 ? 0 : delay; -} - -class MessagePumpForUIQt : public QObject, - public base::MessagePump -{ -public: - MessagePumpForUIQt() - // Usually this gets passed through Run, but since we have - // our own event loop, attach it explicitly ourselves. - : m_delegate(base::MessageLoopForUI::current()) - , m_explicitLoop(0) - , m_timerId(0) - { - } - - void Run(Delegate *delegate) override - { - Q_ASSERT(delegate == m_delegate); - // This is used only when MessagePumpForUIQt is used outside of the GUI thread. - QEventLoop loop; - m_explicitLoop = &loop; - loop.exec(); - m_explicitLoop = 0; - } - - void Quit() override - { - Q_ASSERT(m_explicitLoop); - m_explicitLoop->quit(); - } - - void ScheduleWork() override - { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - } - - void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) override - { - if (delayed_work_time.is_null()) { - killTimer(m_timerId); - m_timerId = 0; - m_timerScheduledTime = base::TimeTicks(); - } else if (!m_timerId || delayed_work_time < m_timerScheduledTime) { - killTimer(m_timerId); - m_timerId = startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); - m_timerScheduledTime = delayed_work_time; - } - } - -protected: - void customEvent(QEvent *ev) override - { - if (handleScheduledWork()) - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - } - - void timerEvent(QTimerEvent *ev) override - { - Q_ASSERT(m_timerId == ev->timerId()); - killTimer(m_timerId); - m_timerId = 0; - m_timerScheduledTime = base::TimeTicks(); - - base::TimeTicks next_delayed_work_time; - m_delegate->DoDelayedWork(&next_delayed_work_time); - ScheduleDelayedWork(next_delayed_work_time); - } - -private: - bool handleScheduledWork() { - bool more_work_is_plausible = m_delegate->DoWork(); - - base::TimeTicks delayed_work_time; - more_work_is_plausible |= m_delegate->DoDelayedWork(&delayed_work_time); - - if (more_work_is_plausible) - return true; - - more_work_is_plausible |= m_delegate->DoIdleWork(); - if (!more_work_is_plausible) - ScheduleDelayedWork(delayed_work_time); - - return more_work_is_plausible; - } - - Delegate *m_delegate; - QEventLoop *m_explicitLoop; - int m_timerId; - base::TimeTicks m_timerScheduledTime; -}; - -std::unique_ptr<base::MessagePump> messagePumpFactory() -{ - return base::WrapUnique(new MessagePumpForUIQt); -} - -} // anonymous namespace - -class BrowserMainPartsQt : public content::BrowserMainParts -{ -public: - BrowserMainPartsQt() - : content::BrowserMainParts() - { } - - void PreMainMessageLoopStart() override - { - base::MessageLoop::InitMessagePumpForUIFactory(messagePumpFactory); - } - - void PostMainMessageLoopRun() override - { - // The BrowserContext's destructor uses the MessageLoop so it should be deleted - // right before the RenderProcessHostImpl's destructor destroys it. - WebEngineContext::current()->destroyBrowserContext(); - } - - int PreCreateThreads() override - { - base::ThreadRestrictions::SetIOAllowed(true); - // Like ChromeBrowserMainExtraPartsViews::PreCreateThreads does. -#if defined(Q_OS_WIN) - display::Screen::SetScreenInstance(new display::win::ScreenWin); -#else - display::Screen::SetScreenInstance(new DesktopScreenQt); -#endif - return 0; - } - -private: - DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt); -}; - class QtShareGLContext : public gl::GLContext { public: QtShareGLContext(QOpenGLContext *qtContext) @@ -334,14 +190,13 @@ public: bool MakeCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } void ReleaseCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); } bool IsCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - void OnSetSwapInterval(int) override { Q_UNREACHABLE(); } scoped_refptr<gl::GPUTimingClient> CreateGPUTimingClient() override { return nullptr; } - const gl::ExtensionSet& GetExtensions() override + const gfx::ExtensionSet& GetExtensions() override { - static const gl::ExtensionSet s_emptySet; + static const gfx::ExtensionSet s_emptySet; return s_emptySet; } void ResetExtensions() override @@ -376,18 +231,10 @@ void ShareGroupQtQuick::AboutToAddFirstContext() ContentBrowserClientQt::ContentBrowserClientQt() : m_browserMainParts(0) { - Q_ASSERT(!gBrowserClient); - gBrowserClient = this; } ContentBrowserClientQt::~ContentBrowserClientQt() { - gBrowserClient = 0; -} - -ContentBrowserClientQt *ContentBrowserClientQt::Get() -{ - return gBrowserClient; } content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const content::MainFunctionParams&) @@ -396,25 +243,38 @@ content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const return m_browserMainParts; } -void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host) +void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host, + service_manager::mojom::ServiceRequest *service_request) { const int id = host->GetID(); Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())), + base::Bind(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id)); + // FIXME: Add a settings variable to enable/disable the file scheme. - content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(id, url::kFileScheme); - static_cast<BrowserContextQt*>(host->GetBrowserContext())->m_adapter->userResourceController()->renderProcessStartedWithHost(host); + content::ChildProcessSecurityPolicy::GetInstance()->GrantRequestScheme(id, url::kFileScheme); + static_cast<ProfileQt*>(host->GetBrowserContext())->m_profileAdapter->userResourceController()->renderProcessStartedWithHost(host); host->AddFilter(new BrowserMessageFilterQt(id, profile)); -#if defined(Q_OS_MACOS) && BUILDFLAG(ENABLE_SPELLCHECK) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) - host->AddFilter(new SpellCheckMessageFilterPlatform(id)); -#endif -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) host->AddFilter(new PrintingMessageFilterQt(host->GetID())); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif + + service_manager::mojom::ServicePtr service; + *service_request = mojo::MakeRequest(&service); + service_manager::mojom::PIDReceiverPtr pid_receiver; + service_manager::Identity renderer_identity = host->GetChildIdentity(); + ServiceQt::GetInstance()->connector()->StartService( + service_manager::Identity("qtwebengine_renderer", + renderer_identity.user_id(), + renderer_identity.instance()), + std::move(service), mojo::MakeRequest(&pid_receiver)); } void ContentBrowserClientQt::ResourceDispatcherHostCreated() { - m_resourceDispatcherHostDelegate.reset(new ResourceDispatcherHostDelegateQt); + m_resourceDispatcherHostDelegate.reset(new content::ResourceDispatcherHostDelegate); content::ResourceDispatcherHost::Get()->SetDelegate(m_resourceDispatcherHostDelegate.get()); } @@ -463,6 +323,7 @@ static int IsCertErrorFatal(int cert_error) case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION: case net::ERR_CERT_VALIDITY_TOO_LONG: case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED: + case net::ERR_CERT_SYMANTEC_LEGACY: return false; case net::ERR_CERT_CONTAINS_ERRORS: case net::ERR_CERT_REVOKED: @@ -500,12 +361,38 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont contentsDelegate->allowCertificateError(errorController); } -void ContentBrowserClientQt::SelectClientCertificate(content::WebContents * /*webContents*/, - net::SSLCertRequestInfo * /*certRequestInfo*/, - net::ClientCertIdentityList /*client_certs*/, +void ContentBrowserClientQt::SelectClientCertificate(content::WebContents *webContents, + net::SSLCertRequestInfo *certRequestInfo, + net::ClientCertIdentityList clientCerts, std::unique_ptr<content::ClientCertificateDelegate> delegate) { - delegate->ContinueWithCertificate(nullptr, nullptr); + if (!clientCerts.empty()) { + WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + + QSharedPointer<ClientCertSelectController> certSelectController( + new ClientCertSelectController(certRequestInfo, std::move(clientCerts), std::move(delegate))); + + contentsDelegate->selectClientCert(certSelectController); + } else { + delegate->ContinueWithCertificate(nullptr, nullptr); + } +} + +std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertStore(content::ResourceContext *resource_context) +{ + if (!resource_context) + return nullptr; +#if defined(USE_NSS_CERTS) + // FIXME: Give it a proper callback for a password delegate. + return std::unique_ptr<net::ClientCertStore>( + new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory())); +#elif defined(OS_WIN) + return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin()); +#elif defined(OS_MACOSX) + return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac()); +#else + return nullptr; +#endif } std::string ContentBrowserClientQt::GetApplicationLocale() @@ -515,15 +402,17 @@ std::string ContentBrowserClientQt::GetApplicationLocale() std::string ContentBrowserClientQt::GetAcceptLangs(content::BrowserContext *context) { - return static_cast<BrowserContextQt*>(context)->adapter()->httpAcceptLanguage().toStdString(); + return static_cast<ProfileQt*>(context)->profileAdapter()->httpAcceptLanguage().toStdString(); } void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) { Q_UNUSED(child_process_id); + url::CustomScheme::SaveSchemes(command_line); + std::string processType = command_line->GetSwitchValueASCII(switches::kProcessType); - if (processType == switches::kZygoteProcess) + if (processType == service_manager::switches::kZygoteProcess) command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale()); } @@ -532,12 +421,6 @@ void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes->push_back(content::kChromeDevToolsScheme); } -void ContentBrowserClientQt::GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) -{ - GetAdditionalWebUISchemes(additional_schemes); - additional_schemes->push_back(kQrcSchemeQt); -} - #if defined(Q_OS_LINUX) void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) { @@ -554,7 +437,7 @@ void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base: } #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) { browser_host->GetPpapiHost()->AddHostFactoryFilter( @@ -617,8 +500,8 @@ private: void ContentBrowserClientQt::InitFrameInterfaces() { - m_frameInterfaces = base::MakeUnique<service_manager::BinderRegistry>(); - m_frameInterfacesParameterized = base::MakeUnique<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>>(); + m_frameInterfaces = std::make_unique<service_manager::BinderRegistry>(); + m_frameInterfacesParameterized = std::make_unique<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>>(); m_frameInterfacesParameterized->AddInterface(base::Bind(&ServiceDriver::BindInsecureInputService)); } @@ -633,59 +516,17 @@ void ContentBrowserClientQt::BindInterfaceRequestFromFrame(content::RenderFrameH m_frameInterfaces->TryBindInterface(interface_name, &interface_pipe); } -class ServiceQt : public service_manager::Service { -public: - ServiceQt(); - - static std::unique_ptr<service_manager::Service> Create() - { - return base::MakeUnique<ServiceQt>(); - } - -private: - // service_manager::Service: - void OnBindInterface(const service_manager::BindSourceInfo& remote_info, - const std::string& name, - mojo::ScopedMessagePipeHandle handle) override; - - service_manager::BinderRegistry m_registry; - service_manager::BinderRegistryWithArgs<const service_manager::BindSourceInfo&> m_registry_with_source_info; - - DISALLOW_COPY_AND_ASSIGN(ServiceQt); -}; - -ServiceQt::ServiceQt() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -#if BUILDFLAG(ENABLE_SPELLCHECK) - m_registry_with_source_info.AddInterface( - base::Bind(&SpellCheckHostChromeImpl::Create), - content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)); -#endif -} - -void ServiceQt::OnBindInterface(const service_manager::BindSourceInfo& remote_info, - const std::string& name, - mojo::ScopedMessagePipeHandle handle) -{ - content::OverrideOnBindInterface(remote_info, name, &handle); - if (!handle.is_valid()) - return; - - if (!m_registry.TryBindInterface(name, &handle)) - m_registry_with_source_info.TryBindInterface(name, &handle, remote_info); -} - -void ContentBrowserClientQt::RegisterInProcessServices(StaticServiceMap* services) +void ContentBrowserClientQt::RegisterInProcessServices(StaticServiceMap* services, content::ServiceManagerConnection* connection) { service_manager::EmbeddedServiceInfo info; - info.factory = base::Bind(&ServiceQt::Create); + info.factory = ServiceQt::GetInstance()->CreateServiceQtFactory(); services->insert(std::make_pair("qtwebengine", info)); } void ContentBrowserClientQt::RegisterOutOfProcessServices(content::ContentBrowserClient::OutOfProcessServiceMap *services) { - (*services)[proxy_resolver::mojom::kProxyResolverServiceName] = toString16(QLatin1String("V8 Proxy Resolver")); + (*services)[proxy_resolver::mojom::kProxyResolverServiceName] = + base::BindRepeating(&base::ASCIIToUTF16, "V8 Proxy Resolver"); } std::unique_ptr<base::Value> ContentBrowserClientQt::GetServiceManifestOverlay(base::StringPiece name) @@ -706,6 +547,13 @@ std::unique_ptr<base::Value> ContentBrowserClientQt::GetServiceManifestOverlay(b return base::JSONReader::Read(manifest_contents); } +std::vector<content::ContentBrowserClient::ServiceManifestInfo> ContentBrowserClientQt::GetExtraServiceManifests() +{ + return std::vector<content::ContentBrowserClient::ServiceManifestInfo>({ + {"qtwebengine_renderer", IDR_QTWEBENGINE_RENDERER_SERVICE_MANIFEST}, + }); +} + bool ContentBrowserClientQt::CanCreateWindow( content::RenderFrameHost* opener, const GURL& opener_url, @@ -748,28 +596,31 @@ bool ContentBrowserClientQt::CanCreateWindow( return (settings && settings->getJavaScriptCanOpenWindowsAutomatically()) || user_gesture; } +#if QT_CONFIG(webengine_geolocation) std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystemLocationProvider() { -#if defined(QT_USE_POSITIONING) return base::WrapUnique(new LocationProviderQt()); -#else - return nullptr; -#endif } +#endif scoped_refptr<net::URLRequestContextGetter> GetSystemRequestContextOnUIThread() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return scoped_refptr<net::URLRequestContextGetter>( - BrowserContextAdapter::defaultContext()->browserContext()->GetRequestContext()); + ProfileAdapter::createDefaultProfileAdapter()->profile()->GetRequestContext()); } -void ContentBrowserClientQt::GetGeolocationRequestContext( - base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)> callback) +void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context) { - content::BrowserThread::PostTaskAndReplyWithResult( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&GetSystemRequestContextOnUIThread), std::move(callback)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + content::RenderProcessHost* host = content::RenderProcessHost::FromID(render_process_id); + if (!host) + return; + + content::BrowserMessageFilter *network_hints_message_filter( + new network_hints::NetworkHintsMessageFilter(context->host_resolver())); + host->AddFilter(network_hints_message_filter); } bool ContentBrowserClientQt::AllowGetCookie(const GURL &url, @@ -789,8 +640,7 @@ bool ContentBrowserClientQt::AllowSetCookie(const GURL &url, const net::CanonicalCookie& /*cookie*/, content::ResourceContext *context, int /*render_process_id*/, - int /*render_frame_id*/, - const net::CookieOptions& /*options*/) + int /*render_frame_id*/) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(context->GetRequestContext()->network_delegate()); @@ -839,6 +689,57 @@ bool ContentBrowserClientQt::AllowWorkerIndexedDB(const GURL &url, return networkDelegate->canSetCookies(url, url, std::string()); } +static void LaunchURL(const GURL& url, + const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, + ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + content::WebContents* webContents = web_contents_getter.Run(); + if (!webContents) + return; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); +} + + +bool ContentBrowserClientQt::HandleExternalProtocol( + const GURL &url, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + int child_id, + content::NavigationUIData *navigation_data, + bool is_main_frame, + ui::PageTransition page_transition, + bool has_user_gesture) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_UNUSED(child_id); + Q_UNUSED(navigation_data); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::BindOnce(&LaunchURL, + url, + web_contents_getter, + page_transition, + is_main_frame, + has_user_gesture)); + return true; +} + +scoped_refptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegate( + net::AuthChallengeInfo *authInfo, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + const content::GlobalRequestID &request_id, + bool /*is_main_frame*/, + const GURL &url, + scoped_refptr<net::HttpResponseHeaders> response_headers, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) +{ + return base::MakeRefCounted<LoginDelegateQt>(authInfo, web_contents_getter, url, first_auth_attempt, std::move(auth_required_callback)); +} + } // namespace QtWebEngineCore DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::ServiceDriver); diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 6b2487944..b2761b311 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -40,11 +40,9 @@ #ifndef CONTENT_BROWSER_CLIENT_QT_H #define CONTENT_BROWSER_CLIENT_QT_H +#include "qtwebenginecoreglobal_p.h" #include "base/memory/ref_counted.h" #include "content/public/browser/content_browser_client.h" -#include "ppapi/features/features.h" - -#include <QtGlobal> namespace net { class URLRequestContextGetter; @@ -54,7 +52,7 @@ namespace content { class BrowserContext; class BrowserMainParts; -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) class BrowserPpapiHost; #endif @@ -63,6 +61,7 @@ class RenderFrameHost; class RenderProcessHost; class RenderViewHostDelegateView; class ResourceContext; +class ResourceDispatcherHostDelegate; class WebContentsViewPort; class WebContents; struct MainFunctionParams; @@ -74,9 +73,9 @@ class GLShareGroup; } namespace QtWebEngineCore { -class BrowserContextQt; + class BrowserMainPartsQt; -class ResourceDispatcherHostDelegateQt; +class ProfileQt; class ShareGroupQtQuick; class ContentBrowserClientQt : public content::ContentBrowserClient { @@ -84,9 +83,9 @@ class ContentBrowserClientQt : public content::ContentBrowserClient { public: ContentBrowserClientQt(); ~ContentBrowserClientQt(); - static ContentBrowserClientQt* Get(); content::BrowserMainParts* CreateBrowserMainParts(const content::MainFunctionParams&) override; - void RenderProcessWillLaunch(content::RenderProcessHost* host) override; + void RenderProcessWillLaunch(content::RenderProcessHost *host, + service_manager::mojom::ServiceRequest* service_request) override; void ResourceDispatcherHostCreated() override; gl::GLShareGroup* GetInProcessGpuShareGroup() override; content::MediaObserver* GetMediaObserver() override; @@ -107,19 +106,20 @@ public: net::SSLCertRequestInfo* cert_request_info, net::ClientCertIdentityList client_certs, std::unique_ptr<content::ClientCertificateDelegate> delegate) override; + std::unique_ptr<net::ClientCertStore> CreateClientCertStore(content::ResourceContext *resource_context) override; content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() override; std::string GetApplicationLocale() override; std::string GetAcceptLangs(content::BrowserContext* context) override; void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) override; - void GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) override; void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) override; void BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; - void RegisterInProcessServices(StaticServiceMap* services) override; + void RegisterInProcessServices(StaticServiceMap* services, content::ServiceManagerConnection* connection) override; void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override; + std::vector<ServiceManifestInfo> GetExtraServiceManifests() override; std::unique_ptr<base::Value> GetServiceManifestOverlay(base::StringPiece name) override; bool CanCreateWindow( content::RenderFrameHost* opener, @@ -148,8 +148,7 @@ public: const net::CanonicalCookie& cookie, content::ResourceContext* context, int render_process_id, - int render_frame_id, - const net::CookieOptions& options) override; + int render_frame_id) override; bool AllowAppCache(const GURL& manifest_url, const GURL& first_party, @@ -170,20 +169,42 @@ public: content::ResourceContext *context, const std::vector<std::pair<int, int> > &render_frames) override; +#if QT_CONFIG(webengine_geolocation) std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override; - void GetGeolocationRequestContext(base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)> callback) override; +#endif + #if defined(Q_OS_LINUX) void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) override; #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override; #endif + scoped_refptr<content::LoginDelegate> CreateLoginDelegate( + net::AuthChallengeInfo *auth_info, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + const content::GlobalRequestID &request_id, + bool is_main_frame, + const GURL &url, + scoped_refptr<net::HttpResponseHeaders> response_headers, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) override; + bool HandleExternalProtocol( + const GURL &url, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + int child_id, + content::NavigationUIData *navigation_data, + bool is_main_frame, + ui::PageTransition page_transition, + bool has_user_gesture) override; + private: void InitFrameInterfaces(); + void AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context); + BrowserMainPartsQt* m_browserMainParts; - std::unique_ptr<ResourceDispatcherHostDelegateQt> m_resourceDispatcherHostDelegate; + std::unique_ptr<content::ResourceDispatcherHostDelegate> m_resourceDispatcherHostDelegate; scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; std::unique_ptr<service_manager::BinderRegistry> m_frameInterfaces; std::unique_ptr<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>> m_frameInterfacesParameterized; diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 37b601bf8..1a3be31be 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -45,8 +45,13 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/version.h" +#include "content/public/common/cdm_info.h" #include "content/public/common/content_constants.h" #include "content/public/common/user_agent.h" +#include "media/base/media_switches.h" +#include "media/base/video_codecs.h" +#include "media/media_buildflags.h" #include "ui/base/layout.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -59,6 +64,42 @@ #include <QLibraryInfo> #include <QString> +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +#include "media/cdm/cdm_paths.h" // nogncheck +#include "third_party/widevine/cdm/widevine_cdm_common.h" +#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. +#define WIDEVINE_CDM_AVAILABLE +#if defined(WIDEVINE_CDM_AVAILABLE) && !defined(WIDEVINE_CDM_IS_COMPONENT) +#define WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT +namespace switches { +const char kCdmWidevinePath[] = "widevine-path"; +} +// File name of the CDM on different platforms. +const char kWidevineCdmFileName[] = +#if defined(OS_MACOSX) + "widevinecdm.plugin"; +#elif defined(OS_WIN) + "widevinecdm.dll"; +#else // OS_LINUX, etc. + "libwidevinecdm.so"; +#endif +#endif + +static QString webenginePluginsPath() +{ + // Look for plugins in /plugins/webengine or application dir. + static bool initialized = false; + static QString potentialPluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath) % QLatin1String("/webengine"); + if (!initialized) { + initialized = true; + if (!QFileInfo::exists(potentialPluginsPath)) + potentialPluginsPath = QCoreApplication::applicationDirPath(); + } + return potentialPluginsPath; +} +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + + #if defined(Q_OS_WIN) #include <shlobj.h> static QString getLocalAppDataDir() @@ -71,7 +112,7 @@ static QString getLocalAppDataDir() } #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) // The plugin logic is based on chrome/common/chrome_content_client.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -81,8 +122,6 @@ static QString getLocalAppDataDir() #include "content/public/common/pepper_plugin_info.h" #include "ppapi/shared_impl/ppapi_permissions.h" -#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. - static const int32_t kPepperFlashPermissions = ppapi::PERMISSION_DEV | ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_BYPASS_USER_GESTURE | @@ -94,18 +133,6 @@ const char kPpapiFlashVersion[] = "ppapi-flash-version"; const char kPpapiWidevinePath[] = "ppapi-widevine-path"; } -const char kCdmSupportedCodecsParamName[] = "codecs"; -const char kCdmSupportedCodecVp8[] = "vp8"; -const char kCdmSupportedCodecVp9[] = "vp9.0"; -#if BUILDFLAG(USE_PROPRIETARY_CODECS) -const char kCdmSupportedCodecAvc1[] = "avc1"; -#endif - -static const char kWidevineCdmPluginExtension[] = ""; - -static const int32_t kWidevineCdmPluginPermissions = ppapi::PERMISSION_DEV - | ppapi::PERMISSION_PRIVATE; - static QString ppapiPluginsPath() { // Look for plugins in /plugins/ppapi or application dir. @@ -165,7 +192,8 @@ void AddPepperFlashFromSystem(std::vector<content::PepperPluginInfo>* plugins) winDir = QString::fromLatin1("C:/Windows"); QDir pluginDir(winDir + "/System32/Macromed/Flash"); pluginDir.setFilter(QDir::Files); - Q_FOREACH (const QFileInfo &info, pluginDir.entryInfoList(QStringList("pepflashplayer*.dll"))) + const QFileInfoList infos = pluginDir.entryInfoList(QStringList("pepflashplayer*.dll")); + for (const QFileInfo &info : infos) pluginPaths << info.absoluteFilePath(); pluginPaths << ppapiPluginsPath() + QStringLiteral("/pepflashplayer.dll"); #endif @@ -207,22 +235,39 @@ void AddPepperFlashFromCommandLine(std::vector<content::PepperPluginInfo>* plugi plugins->push_back(CreatePepperFlashInfo(base::FilePath(flash_path), flash_version)); } -void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) +namespace QtWebEngineCore { + +void ContentClientQt::AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) +{ + AddPepperFlashFromSystem(plugins); + AddPepperFlashFromCommandLine(plugins); +} + +} // namespace QtWebEngineCore +#endif // QT_CONFIG(webengine_pepper_plugins) + +namespace QtWebEngineCore { + +#if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) +static bool IsWidevineAvailable(base::FilePath *cdm_path, + content::CdmCapability *capability) { -#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS) && !defined(WIDEVINE_CDM_IS_COMPONENT) QStringList pluginPaths; - const base::CommandLine::StringType widevine_argument = base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(switches::kPpapiWidevinePath); + const base::CommandLine::StringType widevine_argument = base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(switches::kCdmWidevinePath); if (!widevine_argument.empty()) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { - pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmAdapterFileName); + pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); +#if QT_CONFIG(webengine_pepper_plugins) + pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); +#endif #if defined(Q_OS_OSX) QDir potentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmAdapterFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName); pluginPaths << potentialWidevinePluginPath; } } @@ -233,71 +278,103 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins) for (int i = 0; i < widevineVersionDirs.size(); ++i) { QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); #ifdef WIN64 - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmAdapterFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmFileName); #else - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmAdapterFileName); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmFileName); #endif pluginPaths << potentialWidevinePluginPath; } } #elif defined(Q_OS_LINUX) - pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdmadapter.so") // Google Chrome - << QStringLiteral("/usr/lib/chromium/libwidevinecdmadapter.so") // Arch - << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdmadapter.so") // Ubuntu/neon - << QStringLiteral("/usr/lib64/chromium/libwidevinecdmadapter.so"); // OpenSUSE style + pluginPaths << QStringLiteral("/opt/google/chrome/libwidevinecdm.so") // Google Chrome + << QStringLiteral("/usr/lib/chromium/libwidevinecdm.so") // Arch + << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdm.so") // Ubuntu/neon + << QStringLiteral("/usr/lib64/chromium/libwidevinecdm.so"); // OpenSUSE style #endif } - Q_FOREACH (const QString &pluginPath, pluginPaths) { - base::FilePath path = QtWebEngineCore::toFilePath(pluginPath); - if (base::PathExists(path)) { - content::PepperPluginInfo widevine_cdm; - widevine_cdm.is_out_of_process = true; - widevine_cdm.path = path; - widevine_cdm.name = kWidevineCdmDisplayName; - widevine_cdm.description = kWidevineCdmDescription; - content::WebPluginMimeType widevine_cdm_mime_type( - kWidevineCdmPluginMimeType, - kWidevineCdmPluginExtension, - kWidevineCdmPluginMimeTypeDescription); - + for (const QString &pluginPath : qAsConst(pluginPaths)) { + *cdm_path = QtWebEngineCore::toFilePath(pluginPath); + if (base::PathExists(*cdm_path)) { // Add the supported codecs as if they came from the component manifest. - std::vector<std::string> codecs; - codecs.push_back(kCdmSupportedCodecVp8); - codecs.push_back(kCdmSupportedCodecVp9); + // This list must match the CDM that is being bundled with Chrome. + capability->video_codecs.push_back(media::VideoCodec::kCodecVP8); + capability->video_codecs.push_back(media::VideoCodec::kCodecVP9); #if BUILDFLAG(USE_PROPRIETARY_CODECS) - codecs.push_back(kCdmSupportedCodecAvc1); -#endif // defined(USE_PROPRIETARY_CODECS) - std::string codec_string = - base::JoinString(codecs, ","); - widevine_cdm_mime_type.additional_params.emplace_back( - base::ASCIIToUTF16(kCdmSupportedCodecsParamName), - base::ASCIIToUTF16(codec_string)); - widevine_cdm.mime_types.push_back(widevine_cdm_mime_type); - widevine_cdm.permissions = kWidevineCdmPluginPermissions; - plugins->push_back(widevine_cdm); - break; + capability->video_codecs.push_back(media::VideoCodec::kCodecH264); +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + + // Add the supported encryption schemes as if they came from the + // component manifest. This list must match the CDM that is being + // bundled with Chrome. + capability->encryption_schemes.insert(media::EncryptionMode::kCenc); + capability->encryption_schemes.insert(media::EncryptionMode::kCbcs); + + // Temporary session is always supported. + capability->session_types.insert(media::CdmSessionType::kTemporary); + + return true; } } -#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) && - // !defined(WIDEVINE_CDM_IS_COMPONENT) + return false; } +#endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) -namespace QtWebEngineCore { -void ContentClientQt::AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) +void ContentClientQt::AddContentDecryptionModules(std::vector<content::CdmInfo> *cdms, + std::vector<media::CdmHostFilePath> *cdm_host_file_paths) { - AddPepperFlashFromSystem(plugins); - AddPepperFlashFromCommandLine(plugins); - AddPepperWidevine(plugins); -} - + Q_UNUSED(cdm_host_file_paths); + if (cdms) { +#if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) + base::FilePath cdm_path; + content::CdmCapability capability; + if (IsWidevineAvailable(&cdm_path, &capability)) { + const base::Version version; + cdms->push_back(content::CdmInfo(kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path, + kWidevineCdmFileSystemId, std::move(capability), + kWidevineKeySystem, false)); + } +#endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) + +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) + // Register Clear Key CDM if specified in command line. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + base::FilePath clear_key_cdm_path = command_line->GetSwitchValuePath(switches::kClearKeyCdmPathForTesting); + if (!clear_key_cdm_path.empty() && base::PathExists(clear_key_cdm_path)) { + // TODO(crbug.com/764480): Remove these after we have a central place for + // External Clear Key (ECK) related information. + // Normal External Clear Key key system. + const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; + // A variant of ECK key system that has a different GUID. + const char kExternalClearKeyDifferentGuidTestKeySystem[] = + "org.chromium.externalclearkey.differentguid"; + + // Supported codecs are hard-coded in ExternalClearKeyProperties. + content::CdmCapability capability( + {}, {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs}, + {media::CdmSessionType::kTemporary, + media::CdmSessionType::kPersistentLicense}, + {}); + + // Register kExternalClearKeyDifferentGuidTestKeySystem first separately. + // Otherwise, it'll be treated as a sub-key-system of normal + // kExternalClearKeyKeySystem. See MultipleCdmTypes test in + // ECKEncryptedMediaTest. + cdms->push_back(content::CdmInfo(media::kClearKeyCdmDisplayName, media::kClearKeyCdmDifferentGuid, + base::Version("0.1.0.0"), clear_key_cdm_path, + media::kClearKeyCdmFileSystemId, capability, + kExternalClearKeyDifferentGuidTestKeySystem, false)); + + // Supported codecs are hard-coded in ExternalClearKeyProperties. + cdms->push_back(content::CdmInfo(media::kClearKeyCdmDisplayName, media::kClearKeyCdmGuid, + base::Version("0.1.0.0"), clear_key_cdm_path, + media::kClearKeyCdmFileSystemId, capability, + kExternalClearKeyKeySystem, true)); + } +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + } } -#endif // BUILDFLAG(ENABLE_PLUGINS) - -#include <QCoreApplication> - -namespace QtWebEngineCore { std::string ContentClientQt::getUserAgent() { @@ -325,9 +402,4 @@ std::string ContentClientQt::GetProduct() const return productName.toStdString(); } -void ContentClientQt::AddAdditionalSchemes(Schemes* schemes) -{ - schemes->secure_schemes.push_back(kQrcSchemeQt); -} - } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index 341406380..fbafa6a4b 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -40,9 +40,9 @@ #ifndef CONTENT_CLIENT_QT_H #define CONTENT_CLIENT_QT_H +#include "qtwebenginecoreglobal_p.h" #include "base/strings/string_piece.h" #include "content/public/common/content_client.h" -#include "ppapi/features/features.h" #include "ui/base/layout.h" namespace QtWebEngineCore { @@ -51,10 +51,11 @@ class ContentClientQt : public content::ContentClient { public: static std::string getUserAgent(); -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) override; #endif - void AddAdditionalSchemes(Schemes* schemes) override; + void AddContentDecryptionModules(std::vector<content::CdmInfo> *cdms, + std::vector<media::CdmHostFilePath> *cdm_host_file_paths) override; base::StringPiece GetDataResource(int, ui::ScaleFactor) const override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index a3b8a9d64..2811d5545 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -53,6 +53,8 @@ #include <ui/base/webui/jstemplate_builder.h> #include "net/grit/net_resources.h" #include "net/base/net_module.h" +#include "services/service_manager/sandbox/switches.h" +#include "url/url_util_qt.h" #include "content_client_qt.h" #include "renderer/content_renderer_client_qt.h" @@ -170,7 +172,7 @@ content::ContentRendererClient *ContentMainDelegateQt::CreateContentRendererClie #if defined(OS_LINUX) base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); std::string process_type = parsedCommandLine->GetSwitchValueASCII(switches::kProcessType); - bool no_sandbox = parsedCommandLine->HasSwitch(switches::kNoSandbox); + bool no_sandbox = parsedCommandLine->HasSwitch(service_manager::switches::kNoSandbox); // Reload locale if the renderer process is sandboxed if (process_type == switches::kRendererProcess && !no_sandbox) { @@ -201,7 +203,7 @@ static void SafeOverridePathImpl(const char *keyName, int key, const base::FileP return; // Do not create directories for overridden paths. - if (PathService::OverrideAndCreateIfNeeded(key, path, false, false)) + if (base::PathService::OverrideAndCreateIfNeeded(key, path, false, false)) return; qWarning("Path override failed for key %s and path '%s'", keyName, path.value().c_str()); @@ -216,10 +218,13 @@ bool ContentMainDelegateQt::BasicStartupComplete(int *exit_code) SafeOverridePath(base::DIR_QT_LIBRARY_DATA, WebEngineLibraryInfo::getPath(base::DIR_QT_LIBRARY_DATA)); #endif SafeOverridePath(ui::DIR_LOCALES, WebEngineLibraryInfo::getPath(ui::DIR_LOCALES)); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) SafeOverridePath(base::DIR_APP_DICTIONARIES, WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES)); #endif SetContentClient(new ContentClientQt); + + url::CustomScheme::LoadSchemes(base::CommandLine::ForCurrentProcess()); + return false; } diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index bbe30a33b..ae529d86a 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -1,3 +1,6 @@ +include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) +QT_FOR_CONFIG += webenginecore webenginecore-private + qtConfig(debug_and_release): CONFIG += debug_and_release include(core_common.pri) @@ -35,23 +38,24 @@ qtConfig(egl): CONFIG += egl INCLUDEPATH += $$PWD $$PWD/api SOURCES = \ + accessibility_tree_formatter_qt.cpp \ authentication_dialog_controller.cpp \ browser_accessibility_manager_qt.cpp \ browser_accessibility_qt.cpp \ - browser_context_adapter.cpp \ - browser_context_adapter_client.cpp \ - browser_context_qt.cpp \ browsing_data_remover_delegate_qt.cpp \ + browser_main_parts_qt.cpp \ browser_message_filter_qt.cpp \ certificate_error_controller.cpp \ chromium_gpu_helper.cpp \ chromium_overrides.cpp \ + client_cert_select_controller.cpp \ clipboard_qt.cpp \ color_chooser_qt.cpp \ color_chooser_controller.cpp \ common/qt_ipc_logging.cpp \ common/qt_messages.cpp \ common/user_script_data.cpp \ + compositor.cpp \ content_client_qt.cpp \ content_browser_client_qt.cpp \ content_main_delegate_qt.cpp \ @@ -63,10 +67,9 @@ SOURCES = \ download_manager_delegate_qt.cpp \ favicon_manager.cpp \ file_picker_controller.cpp \ - gl_context_qt.cpp \ - gl_surface_qt.cpp \ javascript_dialog_controller.cpp \ javascript_dialog_manager_qt.cpp \ + login_delegate_qt.cpp \ media_capture_devices_dispatcher.cpp \ native_web_keyboard_event_qt.cpp \ net/cookie_monster_delegate_qt.cpp \ @@ -81,15 +84,20 @@ SOURCES = \ net/url_request_custom_job_proxy.cpp \ net/url_request_qrc_job_qt.cpp \ net/webui_controller_factory_qt.cpp \ + ozone/gl_context_qt.cpp \ ozone/gl_ozone_egl_qt.cpp \ + ozone/gl_surface_qt.cpp \ ozone/gl_surface_egl_qt.cpp \ - ozone/gl_surface_glx_qt.cpp \ ozone/gl_surface_wgl_qt.cpp \ ozone/ozone_platform_qt.cpp \ ozone/platform_window_qt.cpp \ ozone/surface_factory_qt.cpp \ permission_manager_qt.cpp \ process_main.cpp \ + profile_adapter.cpp \ + profile_adapter_client.cpp \ + profile_qt.cpp \ + profile_io_data_qt.cpp \ quota_permission_context_qt.cpp \ quota_request_controller_impl.cpp \ register_protocol_handler_request_controller_impl.cpp \ @@ -101,12 +109,10 @@ SOURCES = \ 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/resource_dispatcher_host_delegate_qt.cpp \ renderer_host/user_resource_controller_host.cpp \ - renderer_host/web_channel_ipc_transport_host.cpp \ resource_bundle_qt.cpp \ resource_context_qt.cpp \ + service/service_qt.cpp \ type_conversion.cpp \ user_script.cpp \ visited_links_manager_qt.cpp \ @@ -122,22 +128,23 @@ SOURCES = \ HEADERS = \ authentication_dialog_controller_p.h \ authentication_dialog_controller.h \ + build_config_qt.h \ browser_accessibility_manager_qt.h \ browser_accessibility_qt.h \ - browser_context_adapter.h \ - browser_context_adapter_client.h \ - browser_context_qt.h \ browsing_data_remover_delegate_qt.h \ + browser_main_parts_qt.h \ browser_message_filter_qt.h \ certificate_error_controller_p.h \ certificate_error_controller.h \ chromium_overrides.h \ + client_cert_select_controller.h \ clipboard_qt.h \ color_chooser_qt.h \ color_chooser_controller_p.h \ color_chooser_controller.h \ common/qt_messages.h \ common/user_script_data.h \ + compositor.h \ content_client_qt.h \ content_browser_client_qt.h \ content_main_delegate_qt.h \ @@ -148,15 +155,13 @@ HEADERS = \ devtools_manager_delegate_qt.h \ download_manager_delegate_qt.h \ chromium_gpu_helper.h \ - favicon_manager_p.h \ favicon_manager.h \ file_picker_controller.h \ - gl_context_qt.h \ - gl_surface_qt.h \ global_descriptors_qt.h \ javascript_dialog_controller_p.h \ javascript_dialog_controller.h \ javascript_dialog_manager_qt.h \ + login_delegate_qt.h \ media_capture_devices_dispatcher.h \ net/cookie_monster_delegate_qt.h \ net/custom_protocol_handler.h \ @@ -169,15 +174,20 @@ HEADERS = \ net/url_request_custom_job_proxy.h \ net/url_request_qrc_job_qt.h \ net/webui_controller_factory_qt.h \ + ozone/gl_context_qt.h \ ozone/gl_ozone_egl_qt.h \ + ozone/gl_surface_qt.h \ ozone/gl_surface_egl_qt.h \ - ozone/gl_surface_glx_qt.h \ ozone/gl_surface_wgl_qt.h \ ozone/ozone_platform_qt.h \ ozone/platform_window_qt.h \ ozone/surface_factory_qt.h \ permission_manager_qt.h \ process_main.h \ + profile_adapter.h \ + profile_adapter_client.h \ + profile_qt.h \ + profile_io_data_qt.h \ proxy_config_service_qt.h \ quota_permission_context_qt.h \ quota_request_controller.h \ @@ -193,18 +203,15 @@ HEADERS = \ 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/resource_dispatcher_host_delegate_qt.h \ renderer_host/user_resource_controller_host.h \ - renderer_host/web_channel_ipc_transport_host.h \ request_controller.h \ resource_context_qt.h \ + service/service_qt.h \ type_conversion.h \ user_script.h \ visited_links_manager_qt.h \ web_contents_adapter.h \ web_contents_adapter_client.h \ - web_contents_adapter_p.h \ web_contents_delegate_qt.h \ web_contents_view_qt.h \ web_engine_context.h \ @@ -213,6 +220,14 @@ HEADERS = \ web_engine_settings.h \ web_event_factory.h + +qtConfig(webengine-system-x11) { + HEADERS += ozone/gl_ozone_glx_qt.h \ + ozone/gl_surface_glx_qt.h + SOURCES += ozone/gl_surface_glx_qt.cpp \ + ozone/gl_ozone_glx_qt.cpp +} + qtConfig(webengine-pepper-plugins) { SOURCES += \ @@ -259,8 +274,15 @@ contains(QT_CONFIG, opengl) { stream_video_node.h } -qtHaveModule(positioning) { +qtConfig(webengine-geolocation) { SOURCES += location_provider_qt.cpp HEADERS += location_provider_qt.h - DEFINES += QT_USE_POSITIONING=1 +} + +qtConfig(webengine-webchannel) { + HEADERS += renderer/web_channel_ipc_transport.h \ + renderer_host/web_channel_ipc_transport_host.h + + SOURCES += renderer/web_channel_ipc_transport.cpp \ + renderer_host/web_channel_ipc_transport_host.cpp } diff --git a/src/core/core_common.pri b/src/core/core_common.pri index a2f7c9eb4..5f9f3c4f6 100644 --- a/src/core/core_common.pri +++ b/src/core/core_common.pri @@ -2,10 +2,14 @@ # gyp/ninja will take care of the compilation, qmake/make will finish with linking and install. TARGET = QtWebEngineCore -QT += qml quick webchannel +QT += qml quick QT_PRIVATE += quick-private gui-private core-private webenginecoreheaders-private -qtHaveModule(positioning):QT += positioning +qtConfig(webengine-geolocation): QT += positioning +qtConfig(webengine-webchannel): QT += webchannel # LTO does not work for Chromium at the moment, so disable it completely for core. CONFIG -= ltcg + +# Chromium requires C++14 +CONFIG += c++14 diff --git a/src/core/core_generator.pro b/src/core/core_generator.pro index cbf126dda..916c211f9 100644 --- a/src/core/core_generator.pro +++ b/src/core/core_generator.pro @@ -1,6 +1,3 @@ -include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) -QT_FOR_CONFIG += webengine-private - include(core_gn_config.pri) TEMPLATE = lib diff --git a/src/core/core_gn_config.pri b/src/core/core_gn_config.pri index fb671ddb2..9b0145dfc 100644 --- a/src/core/core_gn_config.pri +++ b/src/core/core_gn_config.pri @@ -5,6 +5,7 @@ GN_FIND_MOCABLES_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_find_ 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_CORE_INCLUDE_DIRS = $$PWD/service GN_CREATE_PRI = true QMAKE_INTERNAL_INCLUDED_FILES = $$GN_IMPORTS $$GN_INCLUDES $$GN_FILE diff --git a/src/core/core_headers.pro b/src/core/core_headers.pro index 52c6ca57d..21b5d58c3 100644 --- a/src/core/core_headers.pro +++ b/src/core/core_headers.pro @@ -1,5 +1,5 @@ TARGET = QtWebEngineCore CONFIG += no_private_module header_module internal_module no_plist MODULE = webenginecoreheaders - +MODULE_CFG_FILE = qtwebenginecore-config load(qt_module) diff --git a/src/core/core_module.pro b/src/core/core_module.pro index d21985e60..3b5d37f29 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -1,6 +1,3 @@ -include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) -QT_FOR_CONFIG += webengine-private - MODULE = webenginecore include(core_common.pri) diff --git a/src/core/core_project.pro b/src/core/core_project.pro index 2d2bef60d..5980072ea 100644 --- a/src/core/core_project.pro +++ b/src/core/core_project.pro @@ -11,7 +11,7 @@ linking_pri = $$OUT_PWD/$$getConfigDir()/$${TARGET}.pri CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() INCLUDEPATH += $$CHROMIUM_SRC_DIR \ - $$CHROMIUM_SRC_DIR/third_party/WebKit/Source \ + $$CHROMIUM_SRC_DIR/third_party/blink/public \ $$OUT_PWD/$$getConfigDir()/gen SOURCES += $$NINJA_SOURCES diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 7f791df29..84fde7ca2 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -49,7 +49,7 @@ #include "delegated_frame_node.h" #include "chromium_gpu_helper.h" -#include "gl_surface_qt.h" +#include "ozone/gl_surface_qt.h" #include "stream_video_node.h" #include "type_conversion.h" #include "yuv_video_node.h" @@ -72,6 +72,7 @@ #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/service/display/bsp_tree.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" +#include "content/browser/browser_main_loop.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" @@ -140,7 +141,7 @@ private: QSize m_textureSize; bool m_hasAlpha; GLenum m_target; -#if defined(USE_X11) +#if defined(USE_OZONE) bool m_ownsTexture; #endif #ifdef Q_OS_QNX @@ -154,7 +155,6 @@ public: ResourceHolder(const viz::TransferableResource &resource); QSharedPointer<QSGTexture> initTexture(bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); QSGTexture *texture() const { return m_texture.data(); } - viz::TransferableResource &transferableResource() { return m_resource; } viz::ReturnedResource returnResource(); void incImportCount() { ++m_importCount; } bool needsToFetch() const { return !m_resource.is_software && m_texture && !m_texture.data()->textureId(); } @@ -183,13 +183,10 @@ public: virtual ~DelegatedNodeTreeHandler(){} - virtual void setupRenderPassNode(QSGTexture *, const QRect &, QSGNode *) = 0; + virtual void setupRenderPassNode(QSGTexture *, const QRect &, const QRectF &, QSGNode *) = 0; virtual void setupTextureContentNode(QSGTexture *, const QRect &, const QRectF &, - QSGTexture::Filtering, - QSGTextureNode::TextureCoordinatesTransformMode, + QSGImageNode::TextureCoordinatesTransformMode, QSGNode *) = 0; - virtual void setupTiledContentNode(QSGTexture *, const QRect &, const QRectF &, - QSGTexture::Filtering, QSGNode *) = 0; virtual void setupSolidColorNode(const QRect &, const QColor &, QSGNode *) = 0; #ifndef QT_NO_OPENGL @@ -216,28 +213,31 @@ public: { } - void setupRenderPassNode(QSGTexture *layer, const QRect &rect, QSGNode *) override + void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect, QSGNode *) override { Q_ASSERT(layer); Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); QSGInternalImageNode *imageNode = static_cast<QSGInternalImageNode*>(*m_nodeIterator++); imageNode->setTargetRect(rect); imageNode->setInnerTargetRect(rect); + imageNode->setSubSourceRect(layer->convertToNormalizedSourceRect(sourceRect)); imageNode->setTexture(layer); imageNode->update(); } void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, - QSGTexture::Filtering filtering, - QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm, + QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm, QSGNode *) override { Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); + QSGImageNode *textureNode = static_cast<QSGImageNode*>(*m_nodeIterator++); if (textureNode->texture() != texture) { + // Chromium sometimes uses textures that doesn't completely fit + // in which case the geometry needs to be recalculated even if + // rect and src-rect matches. + if (textureNode->texture()->textureSize() != texture->textureSize()) + textureNode->markDirty(QSGImageNode::DirtyGeometry); textureNode->setTexture(texture); - // @TODO: This is a workaround for funky rendering, figure out why this is needed. - textureNode->markDirty(QSGTextureNode::DirtyGeometry); } if (textureNode->textureCoordinatesTransform() != texCoordTransForm) textureNode->setTextureCoordinatesTransform(texCoordTransForm); @@ -245,25 +245,8 @@ public: textureNode->setRect(rect); if (textureNode->sourceRect() != sourceRect) textureNode->setSourceRect(sourceRect); - if (textureNode->filtering() != filtering) - textureNode->setFiltering(filtering); - } - void setupTiledContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, - QSGTexture::Filtering filtering, QSGNode *) override - { - Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end()); - QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++); - if (textureNode->texture() != texture) { - textureNode->setTexture(texture); - // @TODO: This is a workaround for funky rendering, figure out why this is needed. - textureNode->markDirty(QSGTextureNode::DirtyGeometry); - } - if (textureNode->rect() != rect) - textureNode->setRect(rect); - if (textureNode->sourceRect() != sourceRect) - textureNode->setSourceRect(sourceRect); - if (textureNode->filtering() != filtering) - textureNode->setFiltering(filtering); + if (textureNode->filtering() != texture->filtering()) + textureNode->setFiltering(texture->filtering()); } void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) override { @@ -316,14 +299,15 @@ public: { } - void setupRenderPassNode(QSGTexture *layer, const QRect &rect, + void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect, QSGNode *layerChain) override { Q_ASSERT(layer); // Only QSGInternalImageNode currently supports QSGLayer textures. - QSGInternalImageNode *imageNode = m_apiDelegate->createImageNode(); + QSGInternalImageNode *imageNode = m_apiDelegate->createInternalImageNode(); imageNode->setTargetRect(rect); imageNode->setInnerTargetRect(rect); + imageNode->setSubSourceRect(layer->convertToNormalizedSourceRect(sourceRect)); imageNode->setTexture(layer); imageNode->update(); @@ -332,30 +316,15 @@ public: } void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect, - QSGTexture::Filtering filtering, - QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm, + QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm, QSGNode *layerChain) override { - QSGTextureNode *textureNode = m_apiDelegate->createTextureNode(); + QSGImageNode *textureNode = m_apiDelegate->createImageNode(); textureNode->setTextureCoordinatesTransform(texCoordTransForm); textureNode->setRect(rect); textureNode->setSourceRect(sourceRect); 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) override - { - QSGTextureNode *textureNode = m_apiDelegate->createTextureNode(); - textureNode->setRect(rect); - textureNode->setSourceRect(sourceRect); - textureNode->setFiltering(filtering); - textureNode->setTexture(texture); + textureNode->setFiltering(texture->filtering()); layerChain->appendChildNode(textureNode); m_sceneGraphNodes->append(textureNode); @@ -431,7 +400,7 @@ private: static inline QSharedPointer<QSGLayer> findRenderPassLayer(const int &id, const QVector<QPair<int, QSharedPointer<QSGLayer> > > &list) { typedef QPair<int, QSharedPointer<QSGLayer> > Pair; - Q_FOREACH (const Pair &pair, list) + for (const Pair &pair : list) if (pair.first == id) return pair.second; return QSharedPointer<QSGLayer>(); @@ -571,7 +540,7 @@ MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QS , m_textureSize(textureSize) , m_hasAlpha(false) , m_target(GL_TEXTURE_2D) -#if defined(USE_X11) +#if defined(USE_OZONE) , m_ownsTexture(false) #endif { @@ -586,7 +555,7 @@ MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QS MailboxTexture::~MailboxTexture() { -#if defined(USE_X11) +#if defined(USE_OZONE) // This is rare case, where context is not shared // we created extra texture in current context, so // delete it now @@ -651,7 +620,9 @@ QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, R if (!texture) { if (m_resource.is_software) { Q_ASSERT(apiDelegate); - std::unique_ptr<viz::SharedBitmap> sharedBitmap = viz::ServerSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox); + std::unique_ptr<viz::SharedBitmap> sharedBitmap = + content::BrowserMainLoop::GetInstance()->GetServerSharedBitmapManager()->GetSharedBitmapFromId( + m_resource.size, viz::BGRA_8888, m_resource.mailbox_holder.mailbox); // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending // to draw it but Chromium keeps this information in the quads. // The input format is currently always Format_ARGB32_Premultiplied, so assume that all @@ -659,7 +630,9 @@ QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, R // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to // return false. QImage::Format format = quadNeedsBlending ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - QImage image(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format); + QImage image = sharedBitmap + ? QImage(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format) + : QImage(m_resource.size.width(), m_resource.size.height(), format); texture.reset(apiDelegate->createTextureFromImage(image.copy())); } else { #ifndef QT_NO_OPENGL @@ -669,6 +642,7 @@ QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, R Q_UNREACHABLE(); #endif } + texture->setFiltering(m_resource.filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); m_texture = texture; } // All quads using a resource should request the same blending state. @@ -703,12 +677,12 @@ RectClipNode::RectClipNode(const QRectF &rect) DelegatedFrameNode::DelegatedFrameNode() : m_numPendingSyncPoints(0) -#if defined(USE_X11) && !defined(QT_NO_OPENGL) +#if defined(USE_OZONE) && !defined(QT_NO_OPENGL) , m_contextShared(true) #endif { setFlag(UsePreprocess); -#if defined(USE_X11) && !defined(QT_NO_OPENGL) +#if defined(USE_OZONE) && !defined(QT_NO_OPENGL) QOpenGLContext *currentContext = QOpenGLContext::currentContext() ; QOpenGLContext *sharedContext = qt_gl_global_share_context(); if (currentContext && sharedContext && !QOpenGLContext::areSharing(currentContext, sharedContext)) { @@ -748,7 +722,7 @@ void DelegatedFrameNode::preprocess() // Then render any intermediate RenderPass in order. typedef QPair<int, QSharedPointer<QSGLayer> > Pair; - Q_FOREACH (const Pair &pair, m_sgObjects.renderPassLayers) { + for (const Pair &pair : qAsConst(m_sgObjects.renderPassLayers)) { // The layer is non-live, request a one-time update here. pair.second->scheduleUpdate(); // Proceed with the actual update. @@ -1100,13 +1074,14 @@ void DelegatedFrameNode::handleQuad( const viz::RenderPassDrawQuad *renderPassQuad = viz::RenderPassDrawQuad::MaterialCast(quad); if (!renderPassQuad->mask_texture_size.IsEmpty()) { ResourceHolder *resource = findAndHoldResource(renderPassQuad->mask_resource_id(), resourceCandidates); - Q_UNUSED(resource); // FIXME + Q_UNUSED(resource); // FIXME: QTBUG-67652 } - QSGTexture *layer = + QSGLayer *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); if (layer) - nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), currentLayerChain); + nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), toQt(renderPassQuad->tex_coord_rect), currentLayerChain); + break; } case viz::DrawQuad::TEXTURE_CONTENT: { @@ -1123,9 +1098,7 @@ void DelegatedFrameNode::handleQuad( nodeHandler->setupTextureContentNode( texture, toQt(quad->rect), toQt(uv_rect), - resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear - : QSGTexture::Nearest, - tquad->y_flipped ? QSGTextureNode::MirrorVertically : QSGTextureNode::NoTransform, + tquad->y_flipped ? QSGImageNode::MirrorVertically : QSGImageNode::NoTransform, currentLayerChain); break; } @@ -1165,12 +1138,10 @@ void DelegatedFrameNode::handleQuad( case viz::DrawQuad::TILED_CONTENT: { const viz::TileDrawQuad *tquad = viz::TileDrawQuad::MaterialCast(quad); ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates); - nodeHandler->setupTiledContentNode( + nodeHandler->setupTextureContentNode( initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate), toQt(quad->rect), toQt(tquad->tex_coord_rect), - resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear - : QSGTexture::Nearest, - currentLayerChain); + QSGImageNode::NoTransform, currentLayerChain); break; #ifndef QT_NO_OPENGL } @@ -1263,7 +1234,7 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe mailboxesToPull.reserve(mailboxesToFetch.size()); gpu::SyncPointManager *syncPointManager = sync_point_manager(); - base::MessageLoop *gpuMessageLoop = gpu_message_loop(); + scoped_refptr<base::SingleThreadTaskRunner> gpuTaskRunner = gpu_task_runner(); Q_ASSERT(m_numPendingSyncPoints == 0); m_numPendingSyncPoints = mailboxesToFetch.count(); for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) { @@ -1274,14 +1245,14 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe } if (!mailboxesToPull.isEmpty()) { auto task = base::BindOnce(&DelegatedFrameNode::pullTextures, this, std::move(mailboxesToPull)); - gpuMessageLoop->task_runner()->PostTask(FROM_HERE, std::move(task)); + gpuTaskRunner->PostTask(FROM_HERE, std::move(task)); } m_mailboxesFetchedWaitCond.wait(&m_mutex); m_textureFences.swap(transferredFences); } - Q_FOREACH (gl::TransferableFence sync, transferredFences) { + for (gl::TransferableFence sync : qAsConst(transferredFences)) { // We need to wait on the fences on the Qt current context, and // can therefore not use GLFence routines that uses a different // concept of current context. @@ -1289,7 +1260,7 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe deleteChromiumSync(&sync); } -#if defined(USE_X11) +#if defined(USE_OZONE) // Workaround when context is not shared QTBUG-48969 // Make slow copy between two contexts. if (!m_contextShared) { @@ -1304,7 +1275,7 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe GLuint fbo = 0; funcs->glGenFramebuffers(1, &fbo); - Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { + for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) { // Read texture into QImage from shared context. // Switch to shared context. sharedContext->makeCurrent(m_offsurface.data()); @@ -1391,10 +1362,9 @@ void DelegatedFrameNode::fenceAndUnlockQt(DelegatedFrameNode *frameNode) #ifndef QT_NO_OPENGL if (!!gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) { // Create a fence on the Chromium GPU-thread and context - gl::GLFence *fence = gl::GLFence::Create(); + std::unique_ptr<gl::GLFence> fence = gl::GLFence::Create(); // But transfer it to something generic since we need to read it using Qt's OpenGL. frameNode->m_textureFences.append(fence->Transfer()); - delete fence; } if (frameNode->m_numPendingSyncPoints == 0) base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::unlockQt, frameNode)); diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index 5d967841d..e37ad08a3 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -143,7 +143,7 @@ private: QWaitCondition m_mailboxesFetchedWaitCond; QMutex m_mutex; QList<gl::TransferableFence> m_textureFences; -#if defined(USE_X11) +#if defined(USE_OZONE) bool m_contextShared; QScopedPointer<QOffscreenSurface> m_offsurface; #endif diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp index 1f741f526..bd9e0ebe7 100644 --- a/src/core/devtools_frontend_qt.cpp +++ b/src/core/devtools_frontend_qt.cpp @@ -44,8 +44,8 @@ #include "devtools_frontend_qt.h" -#include "browser_context_adapter.h" -#include "browser_context_qt.h" +#include "profile_adapter.h" +#include "profile_qt.h" #include "web_contents_adapter.h" #include "base/json/json_reader.h" @@ -83,6 +83,24 @@ using namespace QtWebEngineCore; namespace { +std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(const net::HttpResponseHeaders *rh) +{ + auto response = std::make_unique<base::DictionaryValue>(); + response->SetInteger("statusCode", rh ? rh->response_code() : 200); + + auto headers = std::make_unique<base::DictionaryValue>(); + size_t iterator = 0; + std::string name; + std::string value; + // TODO(caseq): this probably needs to handle duplicate header names + // correctly by folding them. + while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) + headers->SetString(name, value); + + response->Set("headers", std::move(headers)); + return response; +} + // ResponseWriter ------------------------------------------------------------- class ResponseWriter : public net::URLFetcherResponseWriter { @@ -137,7 +155,7 @@ int ResponseWriter::Finish(int net_error, const net::CompletionCallback &callbac static std::string GetFrontendURL() { - return chrome::kChromeUIDevToolsURL; + return "chrome-devtools://devtools/bundled/devtools_app.html"; } } // namespace @@ -156,7 +174,7 @@ DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> if (!frontendAdapter->isInitialized()) { scoped_refptr<content::SiteInstance> site = - content::SiteInstance::CreateForURL(frontendAdapter->browserContext(), GURL(GetFrontendURL())); + content::SiteInstance::CreateForURL(frontendAdapter->profile(), GURL(GetFrontendURL())); frontendAdapter->initialize(site.get()); } @@ -171,7 +189,7 @@ DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> if (contents->GetURL() == GURL(GetFrontendURL())) { contents->GetController().Reload(content::ReloadType::ORIGINAL_REQUEST_URL, false); } else { - content::NavigationController::LoadURLParams loadParams = content::NavigationController::LoadURLParams(GURL(GetFrontendURL())); + content::NavigationController::LoadURLParams loadParams((GURL(GetFrontendURL()))); loadParams.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FROM_API); contents->GetController().LoadURLWithParams(loadParams); } @@ -189,9 +207,9 @@ DevToolsFrontendQt::DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webCon , m_prefStore(nullptr) , m_weakFactory(this) { - // We use a separate prefstore than BrowserContextQt, because that one is in-memory only, and this + // We use a separate prefstore than one in ProfileQt, because that one is in-memory only, and this // needs to be stored or it will show introduction text on every load. - if (webContentsAdapter->browserContextAdapter()->isOffTheRecord()) + if (webContentsAdapter->profileAdapter()->isOffTheRecord()) m_prefStore = std::move(scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore())); else CreateJsonPreferences(false); @@ -219,7 +237,7 @@ void DevToolsFrontendQt::Focus() void DevToolsFrontendQt::InspectElementAt(int x, int y) { if (m_agentHost) - m_agentHost->InspectElement(this, x, y); + m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), x, y); else { m_inspect_element_at_x = x; m_inspect_element_at_y = y; @@ -271,7 +289,7 @@ void DevToolsFrontendQt::DocumentAvailableInMainFrame() m_agentHost = agent_host; m_agentHost->AttachClient(this); if (m_inspect_element_at_x != -1) { - m_agentHost->InspectElement(this, m_inspect_element_at_x, m_inspect_element_at_y); + m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), m_inspect_element_at_x, m_inspect_element_at_y); m_inspect_element_at_x = -1; m_inspect_element_at_y = -1; } @@ -480,19 +498,9 @@ void DevToolsFrontendQt::OnURLFetchComplete(const net::URLFetcher *source) PendingRequestsMap::iterator it = m_pendingRequests.find(source); DCHECK(it != m_pendingRequests.end()); - base::DictionaryValue response; - auto headers = base::MakeUnique<base::DictionaryValue>(); - net::HttpResponseHeaders* rh = source->GetResponseHeaders(); - response.SetInteger("statusCode", rh ? rh->response_code() : 200); - - size_t iterator = 0; - std::string name; - std::string value; - while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) - headers->SetString(name, value); - response.Set("headers", std::move(headers)); + auto response = BuildObjectForResponse(source->GetResponseHeaders()); - SendMessageAck(it->second, &response); + SendMessageAck(it->second, response.get()); m_pendingRequests.erase(it); delete source; } diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index e926a818f..ecd2a7d40 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -159,7 +159,7 @@ void DevToolsServerQt::start() m_isStarted = true; DevToolsAgentHost::StartRemoteDebuggingServer( - std::move(socketFactory), std::string(), + std::move(socketFactory), base::FilePath(), base::FilePath()); } @@ -184,9 +184,9 @@ std::string DevToolsManagerDelegateQt::GetDiscoveryPageHTML() return ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML).as_string(); } -std::string DevToolsManagerDelegateQt::GetFrontendResource(const std::string& path) +bool DevToolsManagerDelegateQt::HasBundledFrontendResources() { - return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); + return true; } } //namespace QtWebEngineCore diff --git a/src/core/devtools_manager_delegate_qt.h b/src/core/devtools_manager_delegate_qt.h index 1b0e82bc0..3a519a03f 100644 --- a/src/core/devtools_manager_delegate_qt.h +++ b/src/core/devtools_manager_delegate_qt.h @@ -77,7 +77,8 @@ private: class DevToolsManagerDelegateQt : public content::DevToolsManagerDelegate { public: std::string GetDiscoveryPageHTML() override; - std::string GetFrontendResource(const std::string& path) override; + bool HasBundledFrontendResources() override; + void Initialized(const net::IPEndPoint *ip_address) override; }; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 487a831e4..9fe233577 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -39,10 +39,11 @@ #include "download_manager_delegate_qt.h" +#include "content/public/browser/download_item_utils.h" #include "content/public/browser/download_manager.h" -#include "content/public/browser/download_item.h" #include "content/public/browser/save_page_type.h" #include "content/public/browser/web_contents.h" +#include "net/base/net_string_util.h" #include "net/http/http_content_disposition.h" #include <QDir> @@ -52,22 +53,22 @@ #include <QMimeDatabase> #include <QStandardPaths> -#include "browser_context_adapter.h" -#include "browser_context_adapter_client.h" -#include "browser_context_qt.h" +#include "profile_adapter_client.h" +#include "profile_adapter.h" +#include "profile_qt.h" +#include "qtwebenginecoreglobal.h" #include "type_conversion.h" #include "web_contents_delegate_qt.h" -#include "qtwebenginecoreglobal.h" namespace QtWebEngineCore { -DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter) - : m_contextAdapter(contextAdapter) +DownloadManagerDelegateQt::DownloadManagerDelegateQt(ProfileAdapter *profileAdapter) + : m_profileAdapter(profileAdapter) , m_currentId(0) , m_weakPtrFactory(this) , m_nextDownloadIsUserRequested(false) { - Q_ASSERT(m_contextAdapter); + Q_ASSERT(m_profileAdapter); } DownloadManagerDelegateQt::~DownloadManagerDelegateQt() @@ -81,42 +82,42 @@ void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& cal void DownloadManagerDelegateQt::cancelDownload(const content::DownloadTargetCallback& callback) { - callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath(), content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); + callback.Run(base::FilePath(), download::DownloadItem::TARGET_DISPOSITION_PROMPT, download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath(), download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); } void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) { - content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); - content::DownloadItem *download = dlm->GetDownload(downloadId); + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_profileAdapter->profile()); + download::DownloadItem *download = dlm->GetDownload(downloadId); if (download) download->Cancel(/* user_cancel */ true); } void DownloadManagerDelegateQt::pauseDownload(quint32 downloadId) { - content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); - content::DownloadItem *download = dlm->GetDownload(downloadId); + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_profileAdapter->profile()); + download::DownloadItem *download = dlm->GetDownload(downloadId); if (download) download->Pause(); } void DownloadManagerDelegateQt::resumeDownload(quint32 downloadId) { - content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); - content::DownloadItem *download = dlm->GetDownload(downloadId); + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_profileAdapter->profile()); + download::DownloadItem *download = dlm->GetDownload(downloadId); if (download) download->Resume(); } -bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item, +bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* item, const content::DownloadTargetCallback& callback) { // Keep the forced file path if set, also as the temporary file, so the check for existence // will already return that the file exists. Forced file paths seem to be only used for // store downloads and other special downloads, so they might never end up here anyway. if (!item->GetForcedFilePath().empty()) { - callback.Run(item->GetForcedFilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath(), content::DOWNLOAD_INTERRUPT_REASON_NONE); + callback.Run(item->GetForcedFilePath(), download::DownloadItem::TARGET_DISPOSITION_PROMPT, + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath(), download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); return true; } @@ -125,18 +126,18 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i int downloadType = 0; if (m_nextDownloadIsUserRequested) { - downloadType = BrowserContextAdapterClient::UserRequested; + downloadType = ProfileAdapterClient::UserRequested; m_nextDownloadIsUserRequested = false; } else { bool isAttachment = net::HttpContentDisposition(item->GetContentDisposition(), std::string()).is_attachment(); if (isAttachment) - downloadType = BrowserContextAdapterClient::Attachment; + downloadType = ProfileAdapterClient::Attachment; else - downloadType = BrowserContextAdapterClient::DownloadAttribute; + downloadType = ProfileAdapterClient::DownloadAttribute; } if (suggestedFilename.isEmpty()) - suggestedFilename = toQt(net::HttpContentDisposition(item->GetContentDisposition(), std::string()).filename()); + suggestedFilename = toQt(net::HttpContentDisposition(item->GetContentDisposition(), net::kCharsetLatin1).filename()); if (suggestedFilename.isEmpty()) suggestedFilename = toQt(item->GetTargetFilePath().AsUTF8Unsafe()); @@ -166,9 +167,14 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i } item->AddObserver(this); - QList<BrowserContextAdapterClient*> clients = m_contextAdapter->clients(); + QList<ProfileAdapterClient*> clients = m_profileAdapter->clients(); if (!clients.isEmpty()) { - BrowserContextAdapterClient::DownloadItemInfo info = { + content::WebContents *webContents = content::DownloadItemUtils::GetWebContents(item); + WebContentsAdapterClient *adapterClient = nullptr; + if (webContents) + adapterClient = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate())->adapterClient(); + + ProfileAdapterClient::DownloadItemInfo info = { item->GetId(), toQt(item->GetURL()), item->GetState(), @@ -176,15 +182,16 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i item->GetReceivedBytes(), mimeTypeString, suggestedFilePath, - BrowserContextAdapterClient::UnknownSavePageFormat, + ProfileAdapterClient::UnknownSavePageFormat, false /* accepted */, false /* paused */, false /* done */, downloadType, - item->GetLastReason() + item->GetLastReason(), + adapterClient }; - Q_FOREACH (BrowserContextAdapterClient *client, clients) { + for (ProfileAdapterClient *client : qAsConst(clients)) { client->downloadRequested(info); if (info.accepted) break; @@ -204,10 +211,10 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); callback.Run(filePathForCallback, - content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, + download::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension(toFilePathString("download")), - content::DOWNLOAD_INTERRUPT_REASON_NONE); + download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE); } else cancelDownload(callback); @@ -234,7 +241,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content Q_UNUSED(default_extension); Q_UNUSED(can_save_as_complete); - QList<BrowserContextAdapterClient*> clients = m_contextAdapter->clients(); + QList<ProfileAdapterClient*> clients = m_profileAdapter->clients(); if (clients.isEmpty()) return; @@ -255,18 +262,22 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content suggestedFilePath = downloadDir.absoluteFilePath(suggestedFilePath); } - BrowserContextAdapterClient::SavePageFormat suggestedSaveFormat - = static_cast<BrowserContextAdapterClient::SavePageFormat>(spi.requestedFormat); - if (suggestedSaveFormat == BrowserContextAdapterClient::UnknownSavePageFormat) - suggestedSaveFormat = BrowserContextAdapterClient::MimeHtmlSaveFormat; + ProfileAdapterClient::SavePageFormat suggestedSaveFormat + = static_cast<ProfileAdapterClient::SavePageFormat>(spi.requestedFormat); + if (suggestedSaveFormat == ProfileAdapterClient::UnknownSavePageFormat) + suggestedSaveFormat = ProfileAdapterClient::MimeHtmlSaveFormat; // Clear the delegate's SavePageInfo. It's only valid for the page currently being saved. contentsDelegate->setSavePageInfo(SavePageInfo()); - BrowserContextAdapterClient::DownloadItemInfo info = { + WebContentsAdapterClient *adapterClient = nullptr; + if (web_contents) + adapterClient = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->adapterClient(); + + ProfileAdapterClient::DownloadItemInfo info = { m_currentId + 1, toQt(web_contents->GetURL()), - content::DownloadItem::IN_PROGRESS, + download::DownloadItem::IN_PROGRESS, 0, /* totalBytes */ 0, /* receivedBytes */ QStringLiteral("application/x-mimearchive"), @@ -275,11 +286,12 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content acceptedByDefault, false, /* paused */ false, /* done */ - BrowserContextAdapterClient::SavePage, - BrowserContextAdapterClient::NoReason + ProfileAdapterClient::SavePage, + ProfileAdapterClient::NoReason, + adapterClient }; - Q_FOREACH (BrowserContextAdapterClient *client, clients) { + for (ProfileAdapterClient *client : qAsConst(clients)) { client->downloadRequested(info); if (info.accepted) break; @@ -293,10 +305,10 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content m_weakPtrFactory.GetWeakPtr())); } -bool DownloadManagerDelegateQt::IsMostRecentDownloadItemAtFilePath(content::DownloadItem *download) +bool DownloadManagerDelegateQt::IsMostRecentDownloadItemAtFilePath(download::DownloadItem *download) { - content::BrowserContext *context = download->GetBrowserContext(); - std::vector<content::DownloadItem*> all_downloads; + content::BrowserContext *context = content::DownloadItemUtils::GetBrowserContext(download); + std::vector<download::DownloadItem*> all_downloads; content::DownloadManager* manager = content::BrowserContext::GetDownloadManager(context); @@ -307,23 +319,28 @@ bool DownloadManagerDelegateQt::IsMostRecentDownloadItemAtFilePath(content::Down if (item->GetGuid() == download->GetGuid() || item->GetTargetFilePath() != download->GetTargetFilePath()) continue; - if (item->GetState() == content::DownloadItem::IN_PROGRESS) + if (item->GetState() == download::DownloadItem::IN_PROGRESS) return false; } return true; } -void DownloadManagerDelegateQt::savePackageDownloadCreated(content::DownloadItem *item) +void DownloadManagerDelegateQt::savePackageDownloadCreated(download::DownloadItem *item) { OnDownloadUpdated(item); item->AddObserver(this); } -void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *download) +void DownloadManagerDelegateQt::OnDownloadUpdated(download::DownloadItem *download) { - QList<BrowserContextAdapterClient*> clients = m_contextAdapter->clients(); + QList<ProfileAdapterClient*> clients = m_profileAdapter->clients(); if (!clients.isEmpty()) { - BrowserContextAdapterClient::DownloadItemInfo info = { + WebContentsAdapterClient *adapterClient = nullptr; + content::WebContents *webContents = content::DownloadItemUtils::GetWebContents(download); + if (webContents) + adapterClient = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate())->adapterClient(); + + ProfileAdapterClient::DownloadItemInfo info = { download->GetId(), toQt(download->GetURL()), download->GetState(), @@ -331,21 +348,22 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa download->GetReceivedBytes(), toQt(download->GetMimeType()), QString(), - BrowserContextAdapterClient::UnknownSavePageFormat, + ProfileAdapterClient::UnknownSavePageFormat, true /* accepted */, download->IsPaused(), download->IsDone(), 0 /* downloadType (unused) */, - download->GetLastReason() + download->GetLastReason(), + adapterClient }; - Q_FOREACH (BrowserContextAdapterClient *client, clients) { + for (ProfileAdapterClient *client : qAsConst(clients)) { client->downloadUpdated(info); } } } -void DownloadManagerDelegateQt::OnDownloadDestroyed(content::DownloadItem *download) +void DownloadManagerDelegateQt::OnDownloadDestroyed(download::DownloadItem *download) { download->RemoveObserver(this); download->Cancel(/* user_cancel */ false); diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index 7563d5d3b..fa5bd12ec 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -51,25 +51,28 @@ class FilePath; namespace content { class BrowserContext; -class DownloadItem; class WebContents; } +namespace download { +class DownloadItem; +} + namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class DownloadManagerDelegateInstance; class DownloadTargetHelper; class DownloadManagerDelegateQt : public content::DownloadManagerDelegate - , public content::DownloadItem::Observer + , public download::DownloadItem::Observer { public: - DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter); + DownloadManagerDelegateQt(ProfileAdapter *profileAdapter); ~DownloadManagerDelegateQt(); void GetNextId(const content::DownloadIdCallback& callback) override; - bool DetermineDownloadTarget(content::DownloadItem* item, + bool DetermineDownloadTarget(download::DownloadItem* item, const content::DownloadTargetCallback& callback) override; void GetSaveDir(content::BrowserContext* browser_context, @@ -81,7 +84,7 @@ public: const base::FilePath::StringType &default_extension, bool can_save_as_complete, const content::SavePackagePathPickedCallback &callback) override; - bool IsMostRecentDownloadItemAtFilePath(content::DownloadItem* download) override; + bool IsMostRecentDownloadItemAtFilePath(download::DownloadItem* download) override; void cancelDownload(quint32 downloadId); @@ -91,13 +94,13 @@ public: void markNextDownloadAsUserRequested() { m_nextDownloadIsUserRequested = true; } // Inherited from content::DownloadItem::Observer - void OnDownloadUpdated(content::DownloadItem *download) override; - void OnDownloadDestroyed(content::DownloadItem *download) override; + void OnDownloadUpdated(download::DownloadItem *download) override; + void OnDownloadDestroyed(download::DownloadItem *download) override; private: void cancelDownload(const content::DownloadTargetCallback& callback); - void savePackageDownloadCreated(content::DownloadItem *download); - BrowserContextAdapter *m_contextAdapter; + void savePackageDownloadCreated(download::DownloadItem *download); + ProfileAdapter *m_profileAdapter; uint64_t m_currentId; base::WeakPtrFactory<DownloadManagerDelegateQt> m_weakPtrFactory; diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp index 03da67335..de6a0f183 100644 --- a/src/core/favicon_manager.cpp +++ b/src/core/favicon_manager.cpp @@ -38,8 +38,6 @@ ****************************************************************************/ #include "favicon_manager.h" -#include "favicon_manager_p.h" - #include "type_conversion.h" #include "web_contents_adapter_client.h" #include "web_engine_settings.h" @@ -72,19 +70,21 @@ static inline unsigned area(const QSize &size) } -FaviconManagerPrivate::FaviconManagerPrivate(content::WebContents *webContents, WebContentsAdapterClient *viewClient) +FaviconManager::FaviconManager(content::WebContents *webContents, WebContentsAdapterClient *viewClient) : m_webContents(webContents) , m_viewClient(viewClient) - , m_weakFactory(this) + , m_candidateCount(0) + , m_weakFactory(new base::WeakPtrFactory<FaviconManager>(this)) { } -FaviconManagerPrivate::~FaviconManagerPrivate() +FaviconManager::~FaviconManager() { } -int FaviconManagerPrivate::downloadIcon(const QUrl &url) +int FaviconManager::downloadIcon(const QUrl &url) { + static const uint32_t maxSize = 256; static int fakeId = 0; int id; @@ -96,9 +96,9 @@ int FaviconManagerPrivate::downloadIcon(const QUrl &url) id = m_webContents->DownloadImage( toGurl(url), true, // is_favicon - 0, // no max size + maxSize, false, // normal cache policy - base::Bind(&FaviconManagerPrivate::iconDownloadFinished, m_weakFactory.GetWeakPtr())); + base::Bind(&FaviconManager::iconDownloadFinished, m_weakFactory->GetWeakPtr())); } Q_ASSERT(!m_inProgressRequests.contains(id)); @@ -107,7 +107,7 @@ int FaviconManagerPrivate::downloadIcon(const QUrl &url) return id; } -void FaviconManagerPrivate::iconDownloadFinished(int id, +void FaviconManager::iconDownloadFinished(int id, int status, const GURL &url, const std::vector<SkBitmap> &bitmaps, @@ -125,7 +125,7 @@ void FaviconManagerPrivate::iconDownloadFinished(int id, * icons are stored in m_icons explicitly by this function. It is necessary to avoid * m_inProgressRequests being emptied right before the next icon is added by a downloadIcon() call. */ -void FaviconManagerPrivate::downloadPendingRequests() +void FaviconManager::downloadPendingRequests() { for (auto it = m_pendingRequests.cbegin(), end = m_pendingRequests.cend(); it != end; ++it) { QIcon icon; @@ -150,16 +150,15 @@ void FaviconManagerPrivate::downloadPendingRequests() m_pendingRequests.clear(); } -void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon) +void FaviconManager::storeIcon(int id, const QIcon &icon) { - Q_Q(FaviconManager); // Icon download has been interrupted if (!m_inProgressRequests.contains(id)) return; QUrl requestUrl = m_inProgressRequests[id]; - FaviconInfo &faviconInfo = q->m_faviconInfoMap[requestUrl]; + FaviconInfo &faviconInfo = m_faviconInfoMap[requestUrl]; unsigned iconCount = 0; if (!icon.isNull()) @@ -190,13 +189,13 @@ void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon) WebEngineSettings *settings = m_viewClient->webEngineSettings(); bool touchIconsEnabled = settings->testAttribute(WebEngineSettings::TouchIconsEnabled); - q->generateCandidateIcon(touchIconsEnabled); - const QUrl &iconUrl = q->candidateIconUrl(touchIconsEnabled); + generateCandidateIcon(touchIconsEnabled); + const QUrl &iconUrl = candidateIconUrl(touchIconsEnabled); propagateIcon(iconUrl); } } -void FaviconManagerPrivate::propagateIcon(const QUrl &iconUrl) const +void FaviconManager::propagateIcon(const QUrl &iconUrl) const { content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry(); if (entry) { @@ -208,30 +207,15 @@ void FaviconManagerPrivate::propagateIcon(const QUrl &iconUrl) const m_viewClient->iconChanged(iconUrl); } -FaviconManager::FaviconManager(FaviconManagerPrivate *d) - : m_candidateCount(0) -{ - Q_ASSERT(d); - d_ptr.reset(d); - - d->q_ptr = this; -} - -FaviconManager::~FaviconManager() -{ -} - QIcon FaviconManager::getIcon(const QUrl &url) const { - Q_D(const FaviconManager); - if (url.isEmpty()) return m_candidateIcon; - if (!d->m_icons.contains(url)) + if (!m_icons.contains(url)) return QIcon(); - return d->m_icons[url]; + return m_icons[url]; } FaviconInfo FaviconManager::getFaviconInfo(const QUrl &url) const @@ -257,12 +241,11 @@ QList<FaviconInfo> FaviconManager::getFaviconInfoList(bool candidatesOnly) const void FaviconManager::update(const QList<FaviconInfo> &candidates) { - Q_D(FaviconManager); updateCandidates(candidates); - WebEngineSettings *settings = d->m_viewClient->webEngineSettings(); + WebEngineSettings *settings = m_viewClient->webEngineSettings(); if (!settings->testAttribute(WebEngineSettings::AutoLoadIconsForPage)) { - d->m_viewClient->iconChanged(QUrl()); + m_viewClient->iconChanged(QUrl()); return; } @@ -274,16 +257,16 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates) continue; if (it->isValid()) - d->downloadIcon(it->url); + downloadIcon(it->url); } - d->downloadPendingRequests(); + downloadPendingRequests(); // Reset icon if nothing was downloaded - if (d->m_inProgressRequests.isEmpty()) { - content::NavigationEntry *entry = d->m_webContents->GetController().GetVisibleEntry(); + if (m_inProgressRequests.isEmpty()) { + content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry(); if (entry && !entry->GetFavicon().valid) - d->m_viewClient->iconChanged(QUrl()); + m_viewClient->iconChanged(QUrl()); } } @@ -306,11 +289,9 @@ void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates) void FaviconManager::resetCandidates() { - Q_D(FaviconManager); - // Interrupt in progress icon downloads - d->m_pendingRequests.clear(); - d->m_inProgressRequests.clear(); + m_pendingRequests.clear(); + m_inProgressRequests.clear(); m_candidateCount = 0; m_candidateIcon = QIcon(); diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h index e351831c2..f9758d0f0 100644 --- a/src/core/favicon_manager.h +++ b/src/core/favicon_manager.h @@ -37,11 +37,22 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef FAVICON_MANAGER_H #define FAVICON_MANAGER_H -#include "qtwebenginecoreglobal.h" - +#include "qtwebenginecoreglobal_p.h" +#include <memory> #include <QtCore/QMap> #include <QtCore/QObject> #include <QtCore/QSize> @@ -50,12 +61,28 @@ #include "web_engine_settings.h" +class GURL; +class SkBitmap; + +namespace gfx { +class Size; +} + +namespace content { +class WebContents; +} + +namespace base { +template<class T> +class WeakPtrFactory; +} + namespace QtWebEngineCore { -class FaviconManagerPrivate; +class WebContentsAdapterClient; // Based on src/3rdparty/chromium/content/public/common/favicon_url.h -class QWEBENGINE_EXPORT FaviconInfo { +class QWEBENGINECORE_PRIVATE_EXPORT FaviconInfo { public: enum FaviconType { InvalidIcon, @@ -81,9 +108,10 @@ public: }; -class QWEBENGINE_EXPORT FaviconManager : public QObject { - Q_OBJECT +class QWEBENGINECORE_PRIVATE_EXPORT FaviconManager { + public: + FaviconManager(content::WebContents *, WebContentsAdapterClient *); ~FaviconManager(); QIcon getIcon(const QUrl &url = QUrl()) const; @@ -91,24 +119,28 @@ public: QList<FaviconInfo> getFaviconInfoList(bool) const; private: - FaviconManager(FaviconManagerPrivate *); - void update(const QList<FaviconInfo> &); void updateCandidates(const QList<FaviconInfo> &); void resetCandidates(); bool hasCandidate() const; - QUrl candidateIconUrl(bool touchIconsEnabled) const; void generateCandidateIcon(bool touchIconsEnabled); + int downloadIcon(const QUrl &); + void iconDownloadFinished(int, int, const GURL &, const std::vector<SkBitmap> &, const std::vector<gfx::Size> &); + void storeIcon(int, const QIcon &); + void downloadPendingRequests(); + void propagateIcon(const QUrl &) const; +private: + content::WebContents *m_webContents; + WebContentsAdapterClient *m_viewClient; QMap<QUrl, FaviconInfo> m_faviconInfoMap; int m_candidateCount; QIcon m_candidateIcon; - - Q_DISABLE_COPY(FaviconManager) - Q_DECLARE_PRIVATE(FaviconManager) - QScopedPointer<FaviconManagerPrivate> d_ptr; - + QMap<QUrl, QIcon> m_icons; + QMap<int, QUrl> m_inProgressRequests; + QMap<int, QUrl> m_pendingRequests; + std::unique_ptr<base::WeakPtrFactory<FaviconManager>> m_weakFactory; friend class WebContentsDelegateQt; }; diff --git a/src/core/favicon_manager_p.h b/src/core/favicon_manager_p.h deleted file mode 100644 index e2a49dbc7..000000000 --- a/src/core/favicon_manager_p.h +++ /dev/null @@ -1,106 +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 FAVICON_MANAGER_P_H -#define FAVICON_MANAGER_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 "qtwebenginecoreglobal_p.h" - -#include <QtCore/QMap> -#include <QtCore/QObject> -#include <vector> - -#include "base/memory/weak_ptr.h" - -QT_FORWARD_DECLARE_CLASS(QUrl) - -class GURL; -class SkBitmap; - -namespace gfx { - class Size; -} - -namespace content { - class WebContents; -} - -namespace QtWebEngineCore { - -class FaviconManager; -class WebContentsAdapterClient; - -class FaviconManagerPrivate { -public: - FaviconManagerPrivate(content::WebContents *, WebContentsAdapterClient *); - ~FaviconManagerPrivate(); - - int downloadIcon(const QUrl &); - - void iconDownloadFinished(int, int, const GURL &, const std::vector<SkBitmap> &, const std::vector<gfx::Size> &); - void storeIcon(int, const QIcon &); - void downloadPendingRequests(); - void propagateIcon(const QUrl &) const; - - content::WebContents *m_webContents; - WebContentsAdapterClient *m_viewClient; - base::WeakPtrFactory<FaviconManagerPrivate> m_weakFactory; - - QMap<QUrl, QIcon> m_icons; - QMap<int, QUrl> m_inProgressRequests; - QMap<int, QUrl> m_pendingRequests; - - Q_DECLARE_PUBLIC(FaviconManager) - FaviconManager *q_ptr; -}; - -} // namespace QtWebEngineCore - -#endif // FAVICON_MANAGER_P_H diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index 158ff7f67..3ded5ec41 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -70,7 +70,8 @@ void FilePickerController::accepted(const QVariant &files) if (files.canConvert(QVariant::StringList)) { stringList = files.toStringList(); } else if (files.canConvert<QList<QUrl> >()) { - Q_FOREACH (const QUrl &url, files.value<QList<QUrl> >()) + const QList<QUrl> urls = files.value<QList<QUrl>>(); + for (const QUrl &url : urls) stringList.append(url.toLocalFile()); } else { qWarning("An unhandled type '%s' was provided in FilePickerController::accepted(QVariant)", files.typeName()); @@ -87,8 +88,8 @@ void FilePickerController::rejected() static QStringList listRecursively(const QDir &dir) { QStringList ret; - QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden)); - Q_FOREACH (const QFileInfo &fileInfo, infoList) { + const QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden)); + for (const QFileInfo &fileInfo : infoList) { if (fileInfo.isDir()) { ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc ret.append(listRecursively(QDir(fileInfo.absoluteFilePath()))); diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h index 66f28c3fc..7507cf358 100644 --- a/src/core/file_picker_controller.h +++ b/src/core/file_picker_controller.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef FILE_PICKER_CONTROLLER_H #define FILE_PICKER_CONTROLLER_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QObject> #include <QStringList> @@ -50,7 +61,7 @@ namespace content { namespace QtWebEngineCore { -class QWEBENGINE_EXPORT FilePickerController : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT FilePickerController : public QObject { Q_OBJECT public: enum FileChooserMode { diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro index c8c503a39..9860c4541 100644 --- a/src/core/gn_run.pro +++ b/src/core/gn_run.pro @@ -1,5 +1,5 @@ -include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) -QT_FOR_CONFIG += webengine webengine-private +include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) +QT_FOR_CONFIG += webenginecore-private TEMPLATE = aux diff --git a/src/core/javascript_dialog_controller.h b/src/core/javascript_dialog_controller.h index 1cfdfa437..1ba94e095 100644 --- a/src/core/javascript_dialog_controller.h +++ b/src/core/javascript_dialog_controller.h @@ -37,6 +37,17 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef JAVASCRIPT_DIALOG_CONTROLLER_H #define JAVASCRIPT_DIALOG_CONTROLLER_H @@ -48,7 +59,7 @@ namespace QtWebEngineCore { class JavaScriptDialogControllerPrivate; -class QWEBENGINE_EXPORT JavaScriptDialogController : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT JavaScriptDialogController : public QObject { Q_OBJECT public: ~JavaScriptDialogController(); diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp index bfa23d2a1..289947237 100644 --- a/src/core/javascript_dialog_manager_qt.cpp +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -44,7 +44,9 @@ #include "web_contents_view_qt.h" #include "type_conversion.h" + #include "base/memory/singleton.h" +#include "content/browser/web_contents/web_contents_impl.h" namespace QtWebEngineCore { @@ -58,7 +60,13 @@ JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance() return base::Singleton<JavaScriptDialogManagerQt>::get(); } -void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, content::JavaScriptDialogManager::DialogClosedCallback callback, bool *didSuppressMessage) +void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, + content::RenderFrameHost *renderFrameHost, + content::JavaScriptDialogType dialog_type, + const base::string16 &messageText, + const base::string16 &defaultPromptText, + content::JavaScriptDialogManager::DialogClosedCallback callback, + bool *didSuppressMessage) { WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); if (!client) { @@ -66,16 +74,17 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon *didSuppressMessage = true; return; } - + const GURL originUrl = renderFrameHost->GetLastCommittedOrigin().GetURL(); WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(dialog_type); - runDialogForContents(webContents, dialogType, toQt(messageText), toQt(defaultPromptText), toQt(originUrl.GetOrigin()), std::move(callback)); + runDialogForContents(webContents, dialogType, toQt(messageText), toQt(defaultPromptText), toQt(originUrl), std::move(callback)); } -void JavaScriptDialogManagerQt::RunBeforeUnloadDialog(content::WebContents *webContents, content::RenderFrameHost */*render_frame_host*/, +void JavaScriptDialogManagerQt::RunBeforeUnloadDialog(content::WebContents *webContents, content::RenderFrameHost *renderFrameHost, bool isReload, content::JavaScriptDialogManager::DialogClosedCallback callback) { Q_UNUSED(isReload); - runDialogForContents(webContents, WebContentsAdapterClient::UnloadDialog, QString(), QString(), QUrl(), std::move(callback)); + const GURL originUrl = renderFrameHost->GetLastCommittedOrigin().GetURL(); + runDialogForContents(webContents, WebContentsAdapterClient::UnloadDialog, QString(), QString(), toQt(originUrl), std::move(callback)); } bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *contents, bool accept, const base::string16 *promptOverride) diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h index aa82b690f..ca7432a77 100644 --- a/src/core/javascript_dialog_manager_qt.h +++ b/src/core/javascript_dialog_manager_qt.h @@ -60,7 +60,7 @@ public: // For use with the Singleton helper class from chromium static JavaScriptDialogManagerQt *GetInstance(); - void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptDialogType dialog_type, + void RunJavaScriptDialog(content::WebContents *, content::RenderFrameHost *, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, DialogClosedCallback callback, bool *didSuppressMessage) override; diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index d0b783b20..d5a7f1297 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -52,8 +52,8 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "content/public/browser/browser_thread.h" -#include "device/geolocation/geolocation_provider.h" -#include "device/geolocation/geolocation_provider_impl.h" +#include "services/device/geolocation/geolocation_provider.h" +#include "services/device/geolocation/geolocation_provider_impl.h" namespace QtWebEngineCore { @@ -116,7 +116,8 @@ void QtPositioningHelper::start(bool highAccuracy) // Find high accuracy source if the default source is not already one. if (highAccuracy && !isHighAccuracySource(m_positionInfoSource)) { - Q_FOREACH (const QString &name, QGeoPositionInfoSource::availableSources()) { + const QStringList availableSources = QGeoPositionInfoSource::availableSources(); + for (const QString &name : availableSources) { if (name == m_positionInfoSource->sourceName()) continue; QGeoPositionInfoSource *source = QGeoPositionInfoSource::createSource(name, this); diff --git a/src/core/location_provider_qt.h b/src/core/location_provider_qt.h index 5c59b07ed..8e5ad0e54 100644 --- a/src/core/location_provider_qt.h +++ b/src/core/location_provider_qt.h @@ -42,8 +42,8 @@ #include <QtCore/qcompilerdetection.h> -#include "device/geolocation/public/cpp/geoposition.h" -#include "device/geolocation/public/cpp/location_provider.h" +#include "services/device/public/cpp/geolocation/geoposition.h" +#include "services/device/public/cpp/geolocation/location_provider.h" QT_FORWARD_DECLARE_CLASS(QThread) @@ -76,8 +76,6 @@ private: LocationProviderUpdateCallback m_callback; QtPositioningHelper *m_positioningHelper; }; -//#define QT_USE_POSITIONING 1 - } // namespace QtWebEngineCore #endif // LOCATION_PROVIDER_QT_H diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp b/src/core/login_delegate_qt.cpp index eb43f46ad..9659b354a 100644 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp +++ b/src/core/login_delegate_qt.cpp @@ -41,8 +41,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.Chromium file. -#include "resource_dispatcher_host_delegate_qt.h" +#include "login_delegate_qt.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_dispatcher_host.h" @@ -56,56 +57,57 @@ namespace QtWebEngineCore { -ResourceDispatcherHostLoginDelegateQt::ResourceDispatcherHostLoginDelegateQt(net::AuthChallengeInfo *authInfo, net::URLRequest *request) +LoginDelegateQt::LoginDelegateQt( + net::AuthChallengeInfo *authInfo, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + GURL url, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) : m_authInfo(authInfo) - , m_request(request) - , m_url(request->url()) + , m_url(url) + , m_auth_required_callback(std::move(auth_required_callback)) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - const content::ResourceRequestInfo *requestInfo = content::ResourceRequestInfo::ForRequest(request); - Q_ASSERT(requestInfo); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&ResourceDispatcherHostLoginDelegateQt::triggerDialog, + base::Bind(&LoginDelegateQt::triggerDialog, this, - requestInfo->GetWebContentsGetterForRequest())); + web_contents_getter)); } -ResourceDispatcherHostLoginDelegateQt::~ResourceDispatcherHostLoginDelegateQt() +LoginDelegateQt::~LoginDelegateQt() { Q_ASSERT(m_dialogController.isNull()); - // We must have called ClearLoginDelegateForRequest if we didn't receive an OnRequestCancelled. - Q_ASSERT(!m_request); } -void ResourceDispatcherHostLoginDelegateQt::OnRequestCancelled() +void LoginDelegateQt::OnRequestCancelled() { destroy(); // TODO: this should close native dialog, since page can be navigated somewhere else } -QUrl ResourceDispatcherHostLoginDelegateQt::url() const +QUrl LoginDelegateQt::url() const { return toQt(m_url); } -QString ResourceDispatcherHostLoginDelegateQt::realm() const +QString LoginDelegateQt::realm() const { return QString::fromStdString(m_authInfo->realm); } -QString ResourceDispatcherHostLoginDelegateQt::host() const +QString LoginDelegateQt::host() const { return QString::fromStdString(m_authInfo->challenger.host()); } -bool ResourceDispatcherHostLoginDelegateQt::isProxy() const +bool LoginDelegateQt::isProxy() const { return m_authInfo->is_proxy; } -void ResourceDispatcherHostLoginDelegateQt::triggerDialog(const content::ResourceRequestInfo::WebContentsGetter &webContentsGetter) +void LoginDelegateQt::triggerDialog(const content::ResourceRequestInfo::WebContentsGetter &webContentsGetter) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); content::WebContentsImpl *webContents = @@ -119,62 +121,24 @@ void ResourceDispatcherHostLoginDelegateQt::triggerDialog(const content::Resourc client->authenticationRequired(m_dialogController); } -void ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester(bool success, const QString &user, const QString &password) +void LoginDelegateQt::sendAuthToRequester(bool success, const QString &user, const QString &password) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - if (!m_request) - return; - if (success) - m_request->SetAuth(net::AuthCredentials(toString16(user), toString16(password))); - else - m_request->CancelAuth(); - content::ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(m_request); + if (!m_auth_required_callback.is_null()) { + if (success) + std::move(m_auth_required_callback).Run(net::AuthCredentials(toString16(user), toString16(password))); + else + std::move(m_auth_required_callback).Run(base::nullopt); + } destroy(); } -void ResourceDispatcherHostLoginDelegateQt::destroy() +void LoginDelegateQt::destroy() { m_dialogController.reset(); - m_request = nullptr; -} - -static void LaunchURL(const GURL& url, int render_process_id, - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) -{ - Q_UNUSED(render_process_id); - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - content::WebContents* webContents = web_contents_getter.Run(); - if (!webContents) - return; - WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); - contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); -} - - -bool ResourceDispatcherHostDelegateQt::HandleExternalProtocol(const GURL& url, content::ResourceRequestInfo* info) -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&LaunchURL, url, - info->GetChildID(), - info->GetWebContentsGetterForRequest(), - info->GetPageTransition(), - info->IsMainFrame(), - info->HasUserGesture()) - ); - return true; -} - -content::ResourceDispatcherHostLoginDelegate *ResourceDispatcherHostDelegateQt::CreateLoginDelegate(net::AuthChallengeInfo *authInfo, net::URLRequest *request) -{ - // ResourceDispatcherHostLoginDelegateQt is ref-counted and will be released after we called ClearLoginDelegateForRequest. - return new ResourceDispatcherHostLoginDelegateQt(authInfo, request); + m_auth_required_callback.Reset(); } } // namespace QtWebEngineCore diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h b/src/core/login_delegate_qt.h index fa1f8108f..9ce5df843 100644 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.h +++ b/src/core/login_delegate_qt.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -37,25 +37,37 @@ ** ****************************************************************************/ -#ifndef RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H -#define RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H +#ifndef LOGIN_DELEGATE_QT_H +#define LOGIN_DELEGATE_QT_H -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "content/public/browser/resource_dispatcher_host_login_delegate.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/login_delegate.h" +#include "content/public/browser/resource_request_info.h" +#include "url/gurl.h" #include "web_contents_adapter_client.h" +namespace net { +class AuthChallengeInfo; +class AuthCredentials; +} + namespace QtWebEngineCore { class AuthenticationDialogController; -class ResourceDispatcherHostLoginDelegateQt : public content::ResourceDispatcherHostLoginDelegate { +class LoginDelegateQt : public content::LoginDelegate { public: - ResourceDispatcherHostLoginDelegateQt(net::AuthChallengeInfo *authInfo, net::URLRequest *request); - ~ResourceDispatcherHostLoginDelegateQt(); + LoginDelegateQt(net::AuthChallengeInfo *authInfo, + content::ResourceRequestInfo::WebContentsGetter web_contents_getter, + GURL url, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback); + + ~LoginDelegateQt(); - // ResourceDispatcherHostLoginDelegate implementation - virtual void OnRequestCancelled(); + // LoginDelegate implementation + void OnRequestCancelled() override; QUrl url() const; QString realm() const; @@ -70,23 +82,14 @@ private: scoped_refptr<net::AuthChallengeInfo> m_authInfo; - // The request that wants login data. - // Must only be accessed on the IO thread. - net::URLRequest *m_request; GURL m_url; + LoginAuthRequiredCallback m_auth_required_callback; + // This member is used to keep authentication dialog controller alive until // authorization is sent or cancelled. QSharedPointer<AuthenticationDialogController> m_dialogController; }; -class ResourceDispatcherHostDelegateQt : public content::ResourceDispatcherHostDelegate { -public: - bool HandleExternalProtocol(const GURL& url, - content::ResourceRequestInfo* info) override; - - content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(net::AuthChallengeInfo *authInfo, net::URLRequest *request) override; -}; - } // namespace QtWebEngineCore -#endif // RESOURCE_DISPATCHER_HOST_DELEGATE_QT_H +#endif // LOGIN_DELEGATE_QT_H diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 7f521dd10..2bac62084 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -41,7 +41,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.Chromium file. - #include "media_capture_devices_dispatcher.h" #include "javascript_dialog_manager_qt.h" @@ -51,21 +50,21 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/media/webrtc/desktop_streams_registry.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_capture_devices.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/web_contents.h" +#include "content/public/browser/render_process_host.h" #include "content/public/common/origin_util.h" #include "content/public/common/media_stream_request.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_manager_base.h" -#include "media/media_features.h" #include "ui/base/l10n/l10n_util.h" -#if BUILDFLAG(ENABLE_WEBRTC) +#if QT_CONFIG(webengine_webrtc) #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" #endif @@ -81,44 +80,35 @@ namespace { const content::MediaStreamDevice *findDeviceWithId(const content::MediaStreamDevices &devices, const std::string &deviceId) { - content::MediaStreamDevices::const_iterator iter = devices.begin(); - for (; iter != devices.end(); ++iter) { - if (iter->id == deviceId) { - return &(*iter); + content::MediaStreamDevices::const_iterator iter = devices.begin(); + for (; iter != devices.end(); ++iter) { + if (iter->id == deviceId) { + return &(*iter); + } } - } - return 0; -} - -base::string16 getContentsUrl(content::WebContents *webContents) -{ - return base::UTF8ToUTF16(webContents->GetURL().GetOrigin().spec()); + return 0; } // Based on chrome/browser/media/desktop_capture_access_handler.cc: -std::unique_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::MediaStreamDevices *devices, content::DesktopMediaID mediaId - , bool captureAudio, bool /*display_notification*/, base::string16 /*application_title*/) +void getDevicesForDesktopCapture(content::MediaStreamDevices *devices, content::DesktopMediaID mediaId, bool captureAudio) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::unique_ptr<content::MediaStreamUI> ui; + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Add selected desktop source to the list. devices->push_back(content::MediaStreamDevice(content::MEDIA_DESKTOP_VIDEO_CAPTURE, mediaId.ToString(), "Screen")); if (captureAudio) { if (mediaId.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { devices->push_back( - content::MediaStreamDevice(content::MEDIA_DESKTOP_AUDIO_CAPTURE, - mediaId.ToString(), "Tab audio")); + content::MediaStreamDevice(content::MEDIA_DESKTOP_AUDIO_CAPTURE, + mediaId.ToString(), "Tab audio")); } else { - // Use the special loopback device ID for system audio capture. - devices->push_back(content::MediaStreamDevice( - content::MEDIA_DESKTOP_AUDIO_CAPTURE, - media::AudioDeviceDescription::kLoopbackInputDeviceId, - "System Audio")); + // Use the special loopback device ID for system audio capture. + devices->push_back(content::MediaStreamDevice( + content::MEDIA_DESKTOP_AUDIO_CAPTURE, + media::AudioDeviceDescription::kLoopbackInputDeviceId, + "System Audio")); } } - - return std::move(ui); } content::DesktopMediaID getDefaultScreenId() @@ -132,7 +122,7 @@ content::DesktopMediaID getDefaultScreenId() // // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread -#if BUILDFLAG(ENABLE_WEBRTC) && !defined(USE_X11) +#if QT_CONFIG(webengine_webrtc) && !defined(USE_X11) // Source id patterns are different across platforms. // On Linux, the hardcoded value "0" is used. // On Windows, the screens are enumerated consecutively in increasing order from 0. @@ -143,10 +133,10 @@ content::DesktopMediaID getDefaultScreenId() // The code is based on the file // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. webrtc::DesktopCaptureOptions options = - webrtc::DesktopCaptureOptions::CreateDefault(); + webrtc::DesktopCaptureOptions::CreateDefault(); options.set_disable_effects(false); std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( - webrtc::DesktopCapturer::CreateScreenCapturer(options)); + webrtc::DesktopCapturer::CreateScreenCapturer(options)); if (screen_capturer) { webrtc::DesktopCapturer::SourceList screens; @@ -178,12 +168,12 @@ WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const co return requestFlags; } -} // namespace +} // namespace -MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest(const content::MediaStreamRequest &request - , const content::MediaResponseCallback &callback) - : request(request) - , callback(callback) +MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest(const content::MediaStreamRequest &request, + const RepeatingMediaResponseCallback &callback) + : request(request) + , callback(callback) { } @@ -191,43 +181,33 @@ MediaCaptureDevicesDispatcher::PendingAccessRequest::~PendingAccessRequest() { } - -void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content::WebContents *webContents, const QUrl &securityOrigin - , WebContentsAdapterClient::MediaRequestFlags authorizationFlags) +void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content::WebContents *webContents, const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags authorizationFlags) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::unique_ptr<content::MediaStreamUI> ui; content::MediaStreamDevices devices; - std::map<content::WebContents*, RequestsQueue>::iterator it = m_pendingRequests.find(webContents); - - if (it == m_pendingRequests.end()) - // WebContents has been destroyed. Don't need to do anything. + auto it = m_pendingRequests.find(webContents); + if (it == m_pendingRequests.end() || it->second.empty()) return; RequestsQueue &queue(it->second); - if (queue.empty()) - return; - content::MediaStreamRequest &request = queue.front().request; const QUrl requestSecurityOrigin(toQt(request.security_origin)); bool securityOriginsMatch = (requestSecurityOrigin.host() == securityOrigin.host() - && requestSecurityOrigin.scheme() == securityOrigin.scheme() - && requestSecurityOrigin.port() == securityOrigin.port()); + && requestSecurityOrigin.scheme() == securityOrigin.scheme() + && requestSecurityOrigin.port() == securityOrigin.port()); if (!securityOriginsMatch) - qWarning("Security origin mismatch for media access permission: %s requested and %s provided\n", qPrintable(requestSecurityOrigin.toString()) - , qPrintable(securityOrigin.toString())); - + qWarning("Security origin mismatch for media access permission: %s requested and %s provided\n", qPrintable(requestSecurityOrigin.toString()), qPrintable(securityOrigin.toString())); bool microphoneRequested = - (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaAudioCapture); + (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaAudioCapture); bool webcamRequested = - (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaVideoCapture); + (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaVideoCapture); bool desktopAudioRequested = - (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopAudioCapture); + (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopAudioCapture); bool desktopVideoRequested = - (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopVideoCapture); + (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopVideoCapture); if (securityOriginsMatch) { if (microphoneRequested || webcamRequested) { @@ -242,16 +222,11 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: break; } } else if (desktopVideoRequested) { - ui = getDevicesForDesktopCapture( - &devices, - getDefaultScreenId(), - desktopAudioRequested, - /* display_notification: */ false, - getContentsUrl(webContents)); + getDevicesForDesktopCapture(&devices, getDefaultScreenId(), desktopAudioRequested); } } - content::MediaResponseCallback callback = queue.front().callback; + content::MediaResponseCallback callback = std::move(queue.front().callback); queue.pop_front(); if (!queue.empty()) { @@ -259,14 +234,13 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: // asynchronously to make sure that calling infobar is not destroyed until // after this function returns. BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents)); + BrowserThread::UI, FROM_HERE, base::BindOnce(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents)); } - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); + std::move(callback).Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, + std::unique_ptr<content::MediaStreamUI>()); } - - MediaCaptureDevicesDispatcher *MediaCaptureDevicesDispatcher::GetInstance() { return base::Singleton<MediaCaptureDevicesDispatcher>::get(); @@ -274,13 +248,13 @@ MediaCaptureDevicesDispatcher *MediaCaptureDevicesDispatcher::GetInstance() MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() { - // MediaCaptureDevicesDispatcher is a singleton. It should be created on - // UI thread. Otherwise, it will not receive - // content::NOTIFICATION_WEB_CONTENTS_DESTROYED, and that will result in - // possible use after free. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - m_notificationsRegistrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - content::NotificationService::AllSources()); + // MediaCaptureDevicesDispatcher is a singleton. It should be created on + // UI thread. Otherwise, it will not receive + // content::NOTIFICATION_WEB_CONTENTS_DESTROYED, and that will result in + // possible use after free. + DCHECK_CURRENTLY_ON(BrowserThread::UI); + m_notificationsRegistrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, + content::NotificationService::AllSources()); } MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() @@ -289,215 +263,174 @@ MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() void MediaCaptureDevicesDispatcher::Observe(int type, const content::NotificationSource &source, const content::NotificationDetails &details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { - content::WebContents *webContents = content::Source<content::WebContents>(source).ptr(); - m_pendingRequests.erase(webContents); - } + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { + content::WebContents *webContents = content::Source<content::WebContents>(source).ptr(); + m_pendingRequests.erase(webContents); + } } -void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapterClient *adapterClient, content::WebContents *webContents - , const content::MediaStreamRequest &request - , const content::MediaResponseCallback &callback) +void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapterClient *adapterClient, content::WebContents *webContents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Let's not support tab capture for now. if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) { - callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); + std::move(callback).Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); return; } - if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || - request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) { + if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) { const bool screenCaptureEnabled = - adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); + adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); const bool originIsSecure = content::IsOriginSecure(request.security_origin); if (!screenCaptureEnabled || !originIsSecure) { - callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); + std::move(callback).Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); return; } if (!request.requested_video_device_id.empty()) { // Non-empty device id from the chooseDesktopMedia() extension API. - processDesktopCaptureAccessRequest(webContents, request, callback); + processDesktopCaptureAccessRequest(webContents, request, std::move(callback)); return; } } - enqueueMediaAccessRequest(webContents, request, callback); + enqueueMediaAccessRequest(webContents, request, std::move(callback)); // We might not require this approval for pepper requests. adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); } -void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request - , const content::MediaResponseCallback &callback) +void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) { - content::MediaStreamDevices devices; - std::unique_ptr<content::MediaStreamUI> ui; - - if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE || - request.requested_video_device_id.empty()) { - callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui)); - return; - } - - content::WebContents* const web_contents_for_stream = content::WebContents::FromRenderFrameHost( - content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); - content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; - - content::DesktopMediaID mediaId; - if (main_frame) { - // The extension name that the stream is registered with. - std::string originalExtensionName; - // Resolve DesktopMediaID for the specified device id. - mediaId = getDesktopStreamsRegistry()->RequestMediaForStreamId( - request.requested_video_device_id, main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID(), request.security_origin, - &originalExtensionName); - } - - // Received invalid device id. - if (mediaId.type == content::DesktopMediaID::TYPE_NONE) { - callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui)); - return; - } - - // Audio is only supported for screen capture streams. - bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && - request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE); - - ui = getDevicesForDesktopCapture( - &devices, mediaId, capture_audio, true, - getContentsUrl(webContents)); - - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); -} + content::MediaStreamDevices devices; -void MediaCaptureDevicesDispatcher::enqueueMediaAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request - ,const content::MediaResponseCallback &callback) -{ - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.requested_video_device_id.empty()) { + std::move(callback).Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); + return; + } - RequestsQueue &queue = m_pendingRequests[webContents]; - queue.push_back(PendingAccessRequest(request, callback)); + content::WebContents *const web_contents_for_stream = content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); + content::RenderFrameHost *const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; + + content::DesktopMediaID mediaId; + if (main_frame) { + // The extension name that the stream is registered with. + std::string originalExtensionName; + // Resolve DesktopMediaID for the specified device id. + mediaId = getDesktopStreamsRegistry()->RequestMediaForStreamId( + request.requested_video_device_id, main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID(), request.security_origin, + &originalExtensionName); + } + + // Received invalid device id. + if (mediaId.type == content::DesktopMediaID::TYPE_NONE) { + std::move(callback).Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); + return; + } + + // Audio is only supported for screen capture streams. + bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE); + + getDevicesForDesktopCapture(&devices, mediaId, capture_audio); + + std::move(callback).Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, + std::unique_ptr<content::MediaStreamUI>()); } -void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest(content::WebContents *webContents) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); +void MediaCaptureDevicesDispatcher::enqueueMediaAccessRequest(content::WebContents *webContents, + const content::MediaStreamRequest &request, + content::MediaResponseCallback callback) +{ + DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::map<content::WebContents*, RequestsQueue>::iterator it = - m_pendingRequests.find(webContents); + RequestsQueue &queue = m_pendingRequests[webContents]; + queue.push_back(PendingAccessRequest(request, base::AdaptCallbackForRepeating(std::move(callback)))); +} - if (it == m_pendingRequests.end() || it->second.empty()) - return; +void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest(content::WebContents *webContents) +{ + DCHECK_CURRENTLY_ON(BrowserThread::UI); - RequestsQueue &queue(it->second); - if (queue.empty()) - return; + auto it = m_pendingRequests.find(webContents); + if (it == m_pendingRequests.end() || it->second.empty()) + return; - content::MediaStreamRequest &request = queue.front().request; + RequestsQueue &queue(it->second); + content::MediaStreamRequest &request = queue.front().request; - DCHECK(!it->second.empty()); - WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); + WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView())->client(); + adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); } -void MediaCaptureDevicesDispatcher::getDefaultDevices(const std::string &audioDeviceId, const std::string &videoDeviceId, bool audio, bool video - , content::MediaStreamDevices *devices) +void MediaCaptureDevicesDispatcher::getDefaultDevices(const std::string &audioDeviceId, const std::string &videoDeviceId, + bool audio, bool video, content::MediaStreamDevices *devices) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK(audio || video); - - if (audio) { - const content::MediaStreamDevices &audioDevices = content::MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices(); - const content::MediaStreamDevice *device = findDeviceWithId(audioDevices, audioDeviceId); - if (!device && !audioDevices.empty()) - device = &(*audioDevices.begin()); - if (device) - devices->push_back(*device); - } - - if (video) { - const content::MediaStreamDevices &videoDevices = content::MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(); - const content::MediaStreamDevice *device = findDeviceWithId(videoDevices, videoDeviceId); - if (!device && !videoDevices.empty()) - device = &(*videoDevices.begin()); - if (device) - devices->push_back(*device); - } + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(audio || video); + + if (audio) { + const content::MediaStreamDevices &audioDevices = content::MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices(); + const content::MediaStreamDevice *device = findDeviceWithId(audioDevices, audioDeviceId); + if (!device && !audioDevices.empty()) + device = &audioDevices.front(); + if (device) + devices->push_back(*device); + } + + if (video) { + const content::MediaStreamDevices &videoDevices = content::MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(); + const content::MediaStreamDevice *device = findDeviceWithId(videoDevices, videoDeviceId); + if (!device && !videoDevices.empty()) + device = &videoDevices.front(); + if (device) + devices->push_back(*device); + } } DesktopStreamsRegistry *MediaCaptureDevicesDispatcher::getDesktopStreamsRegistry() { - if (!m_desktopStreamsRegistry) - m_desktopStreamsRegistry.reset(new DesktopStreamsRegistry()); - return m_desktopStreamsRegistry.get(); + if (!m_desktopStreamsRegistry) + m_desktopStreamsRegistry.reset(new DesktopStreamsRegistry()); + return m_desktopStreamsRegistry.get(); } -void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) +void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL &security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread, - base::Unretained(this), render_process_id, render_frame_id, - page_request_id, security_origin, stream_type, state)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread, + base::Unretained(this), render_process_id, render_frame_id, + page_request_id, security_origin, stream_type, state)); } void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id, - const GURL& security_origin, - content::MediaStreamType stream_type, + const GURL & /*security_origin*/, + content::MediaStreamType /*stream_type*/, content::MediaRequestState state) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Track desktop capture sessions. Tracking is necessary to avoid unbalanced - // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, - // but they will all reach MEDIA_REQUEST_STATE_CLOSING. - if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || stream_type == content::MEDIA_TAB_VIDEO_CAPTURE) { - if (state == content::MEDIA_REQUEST_STATE_DONE) { - DesktopCaptureSession session = { render_process_id, render_frame_id, - page_request_id }; - m_desktopCaptureSessions.push_back(session); - } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { - for (DesktopCaptureSessions::iterator it = - m_desktopCaptureSessions.begin(); - it != m_desktopCaptureSessions.end(); - ++it) { - if (it->render_process_id == render_process_id && - it->render_view_id == render_frame_id && - it->page_request_id == page_request_id) { - m_desktopCaptureSessions.erase(it); - break; - } - } - } - } - - // Cancel the request. - if (state == content::MEDIA_REQUEST_STATE_CLOSING) { - bool found = false; - for (RequestsQueues::iterator rqs_it = m_pendingRequests.begin(); - rqs_it != m_pendingRequests.end(); ++rqs_it) { - RequestsQueue &queue = rqs_it->second; - for (RequestsQueue::iterator it = queue.begin(); - it != queue.end(); ++it) { - if (it->request.render_process_id == render_process_id && - it->request.render_frame_id == render_frame_id && - it->request.page_request_id == page_request_id) { - queue.erase(it); - found = true; - break; + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Cancel the request. + if (state == content::MEDIA_REQUEST_STATE_CLOSING) { + for (auto &pair : m_pendingRequests) { + RequestsQueue &queue = pair.second; + for (auto it = queue.begin(); it != queue.end(); ++it) { + if (it->request.render_process_id == render_process_id + && it->request.render_frame_id == render_frame_id + && it->request.page_request_id == page_request_id) { + queue.erase(it); + return; + } + } } - } - if (found) - break; } - } } } // namespace QtWebEngineCore diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index 579d159a4..0e5aa38be 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -48,6 +48,7 @@ #include "web_contents_adapter_client.h" #include "base/callback.h" +#include "base/containers/circular_deque.h" #include "base/memory/singleton.h" #include "base/observer_list.h" #include "content/public/browser/media_observer.h" @@ -63,85 +64,78 @@ namespace QtWebEngineCore { // This singleton is used to receive updates about media events from the content // layer. Based on Chrome's implementation. class MediaCaptureDevicesDispatcher : public content::MediaObserver, - public content::NotificationObserver { - public: + public content::NotificationObserver +{ +public: + static MediaCaptureDevicesDispatcher *GetInstance(); - static MediaCaptureDevicesDispatcher *GetInstance(); + void processMediaAccessRequest(WebContentsAdapterClient *, content::WebContents *, const content::MediaStreamRequest &, content::MediaResponseCallback); - void processMediaAccessRequest(WebContentsAdapterClient *, content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); + // Called back from our WebContentsAdapter to grant the requested permission. + void handleMediaAccessPermissionResponse(content::WebContents *, const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags); - // Called back from our WebContentsAdapter to grant the requested permission. - void handleMediaAccessPermissionResponse(content::WebContents *, const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags); +private: + void getDefaultDevices(const std::string &audioDeviceId, const std::string &videoDeviceId, bool audio, bool video, content::MediaStreamDevices *); - void getDefaultDevices(const std::string &audioDeviceId, const std::string &videoDeviceId, bool audio, bool video, content::MediaStreamDevices *); + // Overridden from content::MediaObserver: + void OnAudioCaptureDevicesChanged() override {} + void OnVideoCaptureDevicesChanged() override {} + void OnMediaRequestStateChanged(int render_process_id, + int render_frame_id, + int page_request_id, + const GURL &security_origin, + content::MediaStreamType stream_type, + content::MediaRequestState state) override; - // Overridden from content::MediaObserver: - void OnAudioCaptureDevicesChanged() override { } - void OnVideoCaptureDevicesChanged() override { } - void OnMediaRequestStateChanged(int render_process_id, - int render_frame_id, - int page_request_id, - const GURL& security_origin, - content::MediaStreamType stream_type, - content::MediaRequestState state) override; + void OnCreatingAudioStream(int /*render_process_id*/, int /*render_frame_id*/) override {} + void OnSetCapturingLinkSecured(int /*render_process_id*/, + int /*render_frame_id*/, + int /*page_request_id*/, + content::MediaStreamType /*stream_type*/, + bool /*is_secure*/) override {} - void OnCreatingAudioStream(int /*render_process_id*/, int /*render_frame_id*/) override { } - void OnSetCapturingLinkSecured(int /*render_process_id*/, - int /*render_frame_id*/, - int /*page_request_id*/, - content::MediaStreamType /*stream_type*/, - bool /*is_secure*/) override { } + DesktopStreamsRegistry *getDesktopStreamsRegistry(); - DesktopStreamsRegistry *getDesktopStreamsRegistry(); + friend struct base::DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; - private: - friend struct base::DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; + typedef base::RepeatingCallback<void(const content::MediaStreamDevices &devices, + content::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui)> + RepeatingMediaResponseCallback; - struct PendingAccessRequest { - PendingAccessRequest(const content::MediaStreamRequest &request, - const content::MediaResponseCallback &callback); - ~PendingAccessRequest(); + struct PendingAccessRequest { + PendingAccessRequest(const content::MediaStreamRequest &request, const RepeatingMediaResponseCallback &callback); + ~PendingAccessRequest(); - content::MediaStreamRequest request; - content::MediaResponseCallback callback; - }; - typedef std::deque<PendingAccessRequest> RequestsQueue; - typedef std::map<content::WebContents *, RequestsQueue> RequestsQueues; + content::MediaStreamRequest request; + RepeatingMediaResponseCallback callback; + }; + typedef base::circular_deque<PendingAccessRequest> RequestsQueue; + typedef std::map<content::WebContents *, RequestsQueue> RequestsQueues; - MediaCaptureDevicesDispatcher(); - virtual ~MediaCaptureDevicesDispatcher(); + MediaCaptureDevicesDispatcher(); + virtual ~MediaCaptureDevicesDispatcher(); - // content::NotificationObserver implementation. - void Observe(int type, const content::NotificationSource &source, const content::NotificationDetails &details) override; + // content::NotificationObserver implementation. + void Observe(int type, const content::NotificationSource &source, const content::NotificationDetails &details) override; - // Helpers for ProcessMediaAccessRequest(). - void processDesktopCaptureAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void enqueueMediaAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void ProcessQueuedAccessRequest(content::WebContents *); + // Helpers for ProcessMediaAccessRequest(). + void processDesktopCaptureAccessRequest(content::WebContents *, const content::MediaStreamRequest &, content::MediaResponseCallback); + void enqueueMediaAccessRequest(content::WebContents *, const content::MediaStreamRequest &, content::MediaResponseCallback); + void ProcessQueuedAccessRequest(content::WebContents *); - // Called by the MediaObserver() functions, executed on UI thread. - void updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state); + // Called by the MediaObserver() functions, executed on UI thread. + void updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id, const GURL &security_origin, content::MediaStreamType stream_type, content::MediaRequestState state); - RequestsQueues m_pendingRequests; + RequestsQueues m_pendingRequests; - std::unique_ptr<DesktopStreamsRegistry> m_desktopStreamsRegistry; + std::unique_ptr<DesktopStreamsRegistry> m_desktopStreamsRegistry; - content::NotificationRegistrar m_notificationsRegistrar; + content::NotificationRegistrar m_notificationsRegistrar; - // Tracks MEDIA_DESKTOP_VIDEO_CAPTURE sessions which reach the - // MEDIA_REQUEST_STATE_DONE state. Sessions are remove when - // MEDIA_REQUEST_STATE_CLOSING is encountered. - struct DesktopCaptureSession { - int render_process_id; - int render_view_id; - int page_request_id; - }; - typedef std::list<DesktopCaptureSession> DesktopCaptureSessions; - DesktopCaptureSessions m_desktopCaptureSessions; - - DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher); + DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher); }; } // namespace QtWebEngineCore -#endif // MEDIA_CAPTURE_DEVICES_DISPATCHER_H +#endif // MEDIA_CAPTURE_DEVICES_DISPATCHER_H diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index abc386204..bb89e9e5f 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -55,26 +55,6 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure()); } -static void onSetCookieCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, bool success) { - - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&QWebEngineCookieStorePrivate::onSetCallbackResult, base::Unretained(client), callbackId, success)); -} - -static void onDeleteCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, uint numCookies) { - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&QWebEngineCookieStorePrivate::onDeleteCallbackResult, base::Unretained(client), callbackId, numCookies)); -} - -static void onGetAllCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, const net::CookieList& cookies) { - QByteArray rawCookies; - for (auto&& cookie: cookies) - rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&QWebEngineCookieStorePrivate::onGetAllCallbackResult, base::Unretained(client), callbackId, rawCookies)); -} - CookieMonsterDelegateQt::CookieMonsterDelegateQt() : m_client(0) , m_cookieMonster(nullptr) @@ -88,8 +68,8 @@ CookieMonsterDelegateQt::~CookieMonsterDelegateQt() void CookieMonsterDelegateQt::AddStore(net::CookieStore *store) { - std::unique_ptr<net::CookieStore::CookieChangedSubscription> sub = - store->AddCallbackForAllChanges( + std::unique_ptr<net::CookieChangeSubscription> sub = + store->GetChangeDispatcher().AddCallbackForAllChanges( base::Bind(&CookieMonsterDelegateQt::OnCookieChanged, // this object's destruction will deregister the subscription. base::Unretained(this))); @@ -104,7 +84,8 @@ bool CookieMonsterDelegateQt::hasCookieMonster() void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) { - net::CookieMonster::GetCookieListCallback callback = base::Bind(&onGetAllCookiesCallback, m_client->d_func(), callbackId); + net::CookieMonster::GetCookieListCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread, this, callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); @@ -123,7 +104,7 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie net::CookieStore::SetCookiesCallback callback; if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::Bind(&onSetCookieCallback, m_client->d_func(), callbackId); + callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnIOThread, this, callbackId); GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); @@ -166,7 +147,8 @@ void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + net::CookieMonster::DeleteCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); } @@ -182,7 +164,8 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + net::CookieMonster::DeleteCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); } @@ -226,7 +209,7 @@ void CookieMonsterDelegateQt::setClient(QWebEngineCookieStore *client) m_client->d_func()->processPendingUserCookies(); } -bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &/*cookieLine*/, const QUrl &url) +bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &/*cookieLine*/, const QUrl &url) const { if (!m_client) return true; @@ -234,7 +217,7 @@ bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByt return m_client->d_func()->canAccessCookies(firstPartyUrl, url); } -bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) +bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const { if (!m_client) return true; @@ -242,11 +225,56 @@ bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUr return m_client->d_func()->canAccessCookies(firstPartyUrl, url); } -void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, net::CookieStore::ChangeCause cause) +void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, net::CookieChangeCause cause) { if (!m_client) return; - m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieStore::ChangeCause::INSERTED); + m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieChangeCause::INSERTED); +} + +void CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies) +{ + QByteArray rawCookies; + for (auto &&cookie : cookies) + rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId, rawCookies)); +} + +void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, bool success) +{ + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, success)); } +void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies) +{ + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies)); +} + +void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies) +{ + if (m_client) + m_client->d_func()->onGetAllCallbackResult(callbackId, cookies); +} + +void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, bool success) +{ + if (m_client) + m_client->d_func()->onSetCallbackResult(callbackId, success); +} + +void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies) +{ + if (m_client) + m_client->d_func()->onDeleteCallbackResult(callbackId, numCookies); +} } diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h index 8aceca9c9..7933ba329 100644 --- a/src/core/net/cookie_monster_delegate_qt.h +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef COOKIE_MONSTER_DELEGATE_QT_H #define COOKIE_MONSTER_DELEGATE_QT_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" QT_WARNING_PUSH // For some reason adding -Wno-unused-parameter to QMAKE_CXXFLAGS has no @@ -64,10 +75,10 @@ namespace QtWebEngineCore { static const char* const kCookieableSchemes[] = { "http", "https", "qrc", "ws", "wss" }; -class QWEBENGINE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { +class QWEBENGINECORE_PRIVATE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { QPointer<QWebEngineCookieStore> m_client; net::CookieMonster *m_cookieMonster; - std::vector<std::unique_ptr<net::CookieStore::CookieChangedSubscription>> m_subscriptions; + std::vector<std::unique_ptr<net::CookieChangeSubscription>> m_subscriptions; public: CookieMonsterDelegateQt(); ~CookieMonsterDelegateQt(); @@ -83,11 +94,11 @@ public: void setCookieMonster(net::CookieMonster* monster); void setClient(QWebEngineCookieStore *client); - bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url); - bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url); + bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; + bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; void AddStore(net::CookieStore *store); - void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieStore::ChangeCause cause); + void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause); private: void GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback); @@ -95,6 +106,14 @@ private: void DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name); void DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback); void DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback); + + void GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies); + void SetCookieCallbackOnIOThread(qint64 callbackId, bool success); + void DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies); + + void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies); + void SetCookieCallbackOnUIThread(qint64 callbackId, bool success); + void DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies); }; } diff --git a/src/core/net/custom_protocol_handler.cpp b/src/core/net/custom_protocol_handler.cpp index 402df04ba..5132782c2 100644 --- a/src/core/net/custom_protocol_handler.cpp +++ b/src/core/net/custom_protocol_handler.cpp @@ -46,8 +46,8 @@ namespace QtWebEngineCore { -CustomProtocolHandler::CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter) - : m_adapter(adapter) +CustomProtocolHandler::CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter) + : m_profileAdapter(profileAdapter) { } @@ -56,7 +56,7 @@ net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *reque if (!networkDelegate) return new net::URLRequestErrorJob(request, Q_NULLPTR, net::ERR_ACCESS_DENIED); - return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_adapter); + return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_profileAdapter); } } // namespace diff --git a/src/core/net/custom_protocol_handler.h b/src/core/net/custom_protocol_handler.h index 5d3838834..d5b512b03 100644 --- a/src/core/net/custom_protocol_handler.h +++ b/src/core/net/custom_protocol_handler.h @@ -37,15 +37,26 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef CUSTOM_PROTOCOL_HANDLER_H_ #define CUSTOM_PROTOCOL_HANDLER_H_ -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include "net/url_request/url_request_job_factory.h" #include <QtCore/QByteArray> #include <QtCore/QObject> -#include <QtCore/QWeakPointer> +#include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) @@ -56,20 +67,20 @@ class URLRequestJob; namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; // Implements a ProtocolHandler for custom URL schemes. // If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. -class QWEBENGINE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { +class QWEBENGINECORE_PRIVATE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter); + CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter); net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; private: DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - QWeakPointer<const BrowserContextAdapter> m_adapter; + QPointer<ProfileAdapter> m_profileAdapter; }; } // namespace diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp index 74db51d7d..551302291 100644 --- a/src/core/net/network_delegate_qt.cpp +++ b/src/core/net/network_delegate_qt.cpp @@ -39,13 +39,14 @@ #include "network_delegate_qt.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_request_info.h" #include "cookie_monster_delegate_qt.h" #include "ui/base/page_transition_types.h" -#include "url_request_context_getter_qt.h" +#include "profile_io_data_qt.h" #include "net/base/load_flags.h" #include "net/url_request/url_request.h" #include "qwebengineurlrequestinfo.h" @@ -102,13 +103,13 @@ public: bool isMainFrameRequest, int navigationType, int frameTreeNodeId, - const net::CompletionCallback &callback) + net::CompletionOnceCallback callback) : m_request(request) , m_url(url) , m_isMainFrameRequest(isMainFrameRequest) , m_navigationType(navigationType) , m_frameTreeNodeId(frameTreeNodeId) - , m_callback(callback) + , m_callback(std::move(callback)) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -172,7 +173,7 @@ private: content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestNotification::complete, base::Unretained(this), error)); + base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), error)); } void complete(int error) @@ -181,7 +182,7 @@ private: if (m_request) { if (m_request->status().status() != net::URLRequestStatus::CANCELED) - m_callback.Run(error); + std::move(m_callback).Run(error); m_request->RemoveUserData(UserData::key); } @@ -195,22 +196,22 @@ private: bool m_isMainFrameRequest; int m_navigationType; int m_frameTreeNodeId; - net::CompletionCallback m_callback; + net::CompletionOnceCallback m_callback; }; const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLRequestNotification"; } // namespace -NetworkDelegateQt::NetworkDelegateQt(URLRequestContextGetterQt *requestContext) - : m_requestContextGetter(requestContext) +NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data) + : m_profileIOData(data) { } -int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *newUrl) +int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *newUrl) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_requestContextGetter); + Q_ASSERT(m_profileIOData); const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); @@ -224,7 +225,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C const QUrl qUrl = toQt(request->url()); - QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_requestInterceptor; + QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->requestInterceptor(); if (interceptor) { QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), toQt(navigationType), @@ -264,7 +265,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C resourceInfo->IsMainFrame(), navigationType, frameTreeNodeId, - callback + std::move(callback) ); // We'll run the callback after we notified the UI thread. @@ -298,17 +299,17 @@ bool NetworkDelegateQt::OnCanEnablePrivacyMode(const GURL &url, const GURL &site bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const { - Q_ASSERT(m_requestContextGetter); - return m_requestContextGetter->m_cookieDelegate->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); + Q_ASSERT(m_profileIOData); + return m_profileIOData->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); } bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const { - Q_ASSERT(m_requestContextGetter); - return m_requestContextGetter->m_cookieDelegate->canGetCookies(toQt(first_party), toQt(url)); + Q_ASSERT(m_profileIOData); + return m_profileIOData->canGetCookies(toQt(first_party), toQt(url)); } -int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers) +int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *, net::CompletionOnceCallback, net::HttpRequestHeaders *) { return net::OK; } @@ -322,7 +323,7 @@ void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net:: { } -int NetworkDelegateQt::OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) +int NetworkDelegateQt::OnHeadersReceived(net::URLRequest*, net::CompletionOnceCallback, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) { return net::OK; } @@ -347,7 +348,7 @@ void NetworkDelegateQt::OnPACScriptError(int, const base::string16&) { } -net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) +net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, AuthCallback, net::AuthCredentials*) { return AUTH_REQUIRED_RESPONSE_NO_ACTION; } @@ -372,9 +373,9 @@ bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin& origin) con return false; } -bool NetworkDelegateQt::OnCanSendReportingReport(const url::Origin& origin) const +void NetworkDelegateQt::OnCanSendReportingReports(std::set<url::Origin> origins, base::OnceCallback<void(std::set<url::Origin>)> result_callback) const { - return false; + std::move(result_callback).Run(std::set<url::Origin>()); } bool NetworkDelegateQt::OnCanSetReportingClient(const url::Origin& origin, const GURL& endpoint) const diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h index b5165d229..e4ff196aa 100644 --- a/src/core/net/network_delegate_qt.h +++ b/src/core/net/network_delegate_qt.h @@ -52,29 +52,29 @@ class WebContents; namespace QtWebEngineCore { -class URLRequestContextGetterQt; +class ProfileIODataQt; class NetworkDelegateQt : public net::NetworkDelegate { - URLRequestContextGetterQt *m_requestContextGetter; + ProfileIODataQt *m_profileIOData; public: - NetworkDelegateQt(URLRequestContextGetterQt *requestContext); + NetworkDelegateQt(ProfileIODataQt *data); // net::NetworkDelegate implementation - int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* newUrl) override; + int OnBeforeURLRequest(net::URLRequest* request, net::CompletionOnceCallback callback, GURL* new_url) override; void OnURLRequestDestroyed(net::URLRequest* request) override; bool OnCanSetCookie(const net::URLRequest& request, const net::CanonicalCookie& cookie, net::CookieOptions* options) override; - int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers) override; + int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionOnceCallback callback, net::HttpRequestHeaders *headers) override; void OnBeforeSendHeaders(net::URLRequest* request, const net::ProxyInfo& proxy_info, const net::ProxyRetryInfoMap& proxy_retry_info, net::HttpRequestHeaders* headers) override; void OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) override; - int OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override; + int OnHeadersReceived(net::URLRequest*, net::CompletionOnceCallback, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override; void OnBeforeRedirect(net::URLRequest*, const GURL&) override; void OnResponseStarted(net::URLRequest*, int) override; void OnNetworkBytesReceived(net::URLRequest*, int64_t) override; void OnNetworkBytesSent(net::URLRequest *, int64_t) override; void OnCompleted(net::URLRequest *request, bool started, int net_error) override; void OnPACScriptError(int, const base::string16&) override; - net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) override; + net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, AuthCallback, net::AuthCredentials*) override; bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&) override; bool OnCanAccessFile(const net::URLRequest&, const base::FilePath&, const base::FilePath&) const override; bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override; @@ -82,7 +82,7 @@ public: bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const override; bool OnCanQueueReportingReport(const url::Origin& origin) const override; - bool OnCanSendReportingReport(const url::Origin& origin) const override; + void OnCanSendReportingReports(std::set<url::Origin> origins, base::OnceCallback<void(std::set<url::Origin>)> result_callback) const override; bool OnCanSetReportingClient(const url::Origin& origin, const GURL& endpoint) const override; bool OnCanUseReportingClient(const url::Origin& origin, const GURL& endpoint) const override; diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp index 7fca18eb6..13b969281 100644 --- a/src/core/net/proxy_config_service_qt.cpp +++ b/src/core/net/proxy_config_service_qt.cpp @@ -91,14 +91,12 @@ void ProxyConfigServiceQt::RemoveObserver(net::ProxyConfigService::Observer *obs m_observers.RemoveObserver(observer); } -net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfig *config) +net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfigWithAnnotation *config) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) m_usesSystemConfiguration = QNetworkProxyFactory::usesSystemConfiguration(); -#endif if (m_usesSystemConfiguration) { // Use Chromium's base service to retrieve system settings - net::ProxyConfig systemConfig; + net::ProxyConfigWithAnnotation systemConfig; ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET; if (m_baseService.get()) systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); @@ -112,7 +110,7 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy const QNetworkProxy &qtProxy = QNetworkProxy::applicationProxy(); if (qtProxy == m_qtApplicationProxy && !m_qtProxyConfig.proxy_rules().empty()) { // no changes - *config = m_qtProxyConfig; + *config = net::ProxyConfigWithAnnotation(m_qtProxyConfig, config->traffic_annotation()); return CONFIG_VALID; } @@ -124,24 +122,24 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy switch (qtProxy.type()) { case QNetworkProxy::HttpProxy: case QNetworkProxy::Socks5Proxy: - qtRules.type = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + qtRules.type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST; qtRules.single_proxies.SetSingleProxyServer(server); break; case QNetworkProxy::HttpCachingProxy: - qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; qtRules.proxies_for_http.SetSingleProxyServer(server); break; case QNetworkProxy::FtpCachingProxy: - qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; qtRules.proxies_for_ftp.SetSingleProxyServer(server); break; default: - qtRules.type = net::ProxyConfig::ProxyRules::TYPE_NO_RULES; + qtRules.type = net::ProxyConfig::ProxyRules::Type::EMPTY; } qtRules.bypass_rules.AddRuleToBypassLocal(); // don't use proxy for connections to localhost m_qtProxyConfig.proxy_rules() = qtRules; - *config = m_qtProxyConfig; + *config = net::ProxyConfigWithAnnotation(m_qtProxyConfig, config->traffic_annotation()); return CONFIG_VALID; } @@ -149,7 +147,6 @@ void ProxyConfigServiceQt::OnLazyPoll() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); -#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) // We need to update if // - setUseSystemConfiguration() was called in between // - user changed application proxy @@ -160,14 +157,10 @@ void ProxyConfigServiceQt::OnLazyPoll() if (m_baseService.get()) m_baseService->OnLazyPoll(); } -#else - if (m_qtApplicationProxy != QNetworkProxy::applicationProxy()) - Update(); -#endif } // Called when the base service changed -void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfig &config, ConfigAvailability availability) +void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfigWithAnnotation &config, ConfigAvailability availability) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); Q_UNUSED(config); @@ -181,7 +174,7 @@ void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfig &config, // Update our observers void ProxyConfigServiceQt::Update() { - net::ProxyConfig actual_config; + net::ProxyConfigWithAnnotation actual_config; ConfigAvailability availability = GetLatestProxyConfig(&actual_config); if (availability == CONFIG_PENDING) return; diff --git a/src/core/net/proxy_config_service_qt.h b/src/core/net/proxy_config_service_qt.h index 7be3289d0..dcd303894 100644 --- a/src/core/net/proxy_config_service_qt.h +++ b/src/core/net/proxy_config_service_qt.h @@ -43,14 +43,14 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "net/proxy/proxy_config.h" -#include "net/proxy/proxy_config_service.h" +#include "net/proxy_resolution/proxy_config_service.h" +#include "net/proxy_resolution/proxy_config_with_annotation.h" #include <QNetworkProxy> class ProxyConfigServiceQt - : public net::ProxyConfigService, - public net::ProxyConfigService::Observer { + : public net::ProxyConfigService + , public net::ProxyConfigService::Observer { public: static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &); @@ -61,12 +61,12 @@ public: // ProxyConfigService implementation: void AddObserver(net::ProxyConfigService::Observer *observer) override; void RemoveObserver(net::ProxyConfigService::Observer *observer) override; - ConfigAvailability GetLatestProxyConfig(net::ProxyConfig *config) override; + ConfigAvailability GetLatestProxyConfig(net::ProxyConfigWithAnnotation *config) override; void OnLazyPoll() override; private: // ProxyConfigService::Observer implementation: - void OnProxyConfigChanged(const net::ProxyConfig& config, + void OnProxyConfigChanged(const net::ProxyConfigWithAnnotation &config, ConfigAvailability availability) override; // Retrieve new proxy settings and notify observers. diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp index d8f73abda..ecc3c681e 100644 --- a/src/core/net/ssl_host_state_delegate_qt.cpp +++ b/src/core/net/ssl_host_state_delegate_qt.cpp @@ -58,7 +58,7 @@ CertPolicy::~CertPolicy() // For an allowance, we consider a given |cert| to be a match to a saved // allowed cert if the |error| is an exact match to or subset of the errors // in the saved CertStatus. -bool CertPolicy::Check(const net::X509Certificate &cert, net::CertStatus error) const +bool CertPolicy::Check(const net::X509Certificate &cert, int error) const { net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256(); auto allowed_iter = m_allowed.find(fingerprint); @@ -67,7 +67,7 @@ bool CertPolicy::Check(const net::X509Certificate &cert, net::CertStatus error) return false; } -void CertPolicy::Allow(const net::X509Certificate& cert, net::CertStatus error) +void CertPolicy::Allow(const net::X509Certificate& cert, int error) { net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256(); m_allowed[fingerprint] |= error; @@ -81,7 +81,7 @@ SSLHostStateDelegateQt::~SSLHostStateDelegateQt() { } -void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, net::CertStatus error) +void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, int error) { m_certPolicyforHost[host].Allow(cert, error); } @@ -109,7 +109,7 @@ void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string&) // prior to this query, otherwise false. content::SSLHostStateDelegate::CertJudgment SSLHostStateDelegateQt::QueryPolicy( const std::string &host, const net::X509Certificate &cert, - net::CertStatus error,bool *expired_previous_decision) + int error, bool */*expired_previous_decision*/) { return m_certPolicyforHost[host].Check(cert, error) ? SSLHostStateDelegate::ALLOWED : SSLHostStateDelegate::DENIED; } diff --git a/src/core/net/ssl_host_state_delegate_qt.h b/src/core/net/ssl_host_state_delegate_qt.h index 3ebabb601..b1b49bcf3 100644 --- a/src/core/net/ssl_host_state_delegate_qt.h +++ b/src/core/net/ssl_host_state_delegate_qt.h @@ -41,7 +41,7 @@ #define SSL_HOST_STATE_DELEGATE_QT_H #include "content/public/browser/ssl_host_state_delegate.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" namespace QtWebEngineCore { @@ -49,12 +49,12 @@ class CertPolicy { public: CertPolicy(); ~CertPolicy(); - bool Check(const net::X509Certificate& cert, net::CertStatus error) const; - void Allow(const net::X509Certificate& cert, net::CertStatus error); + bool Check(const net::X509Certificate& cert, int error) const; + void Allow(const net::X509Certificate& cert, int error); bool HasAllowException() const { return m_allowed.size() > 0; } private: - std::map<net::SHA256HashValue, net::CertStatus> m_allowed; + std::map<net::SHA256HashValue, int> m_allowed; }; class SSLHostStateDelegateQt : public content::SSLHostStateDelegate { @@ -64,10 +64,10 @@ public: ~SSLHostStateDelegateQt(); // content::SSLHostStateDelegate implementation: - void AllowCert(const std::string &, const net::X509Certificate &cert, net::CertStatus error) override; + void AllowCert(const std::string &, const net::X509Certificate &cert, int error) override; void Clear(const base::Callback<bool(const std::string&)>& host_filter) override; - virtual CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, - net::CertStatus error,bool *expired_previous_decision) override; + CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, + int error, bool *expired_previous_decision) override; void HostRanInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) override; bool DidHostRunInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) const override; void RevokeUserAllowExceptions(const std::string &host) override; diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp index e964aff65..636d27358 100644 --- a/src/core/net/url_request_context_getter_qt.cpp +++ b/src/core/net/url_request_context_getter_qt.cpp @@ -38,615 +38,23 @@ ****************************************************************************/ #include "url_request_context_getter_qt.h" - -#include "base/memory/ptr_util.h" -#include "base/task_scheduler/post_task.h" -#include "base/threading/sequenced_worker_pool.h" -#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" -#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" -#include "content/network/proxy_service_mojo.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/browsing_data_remover.h" -#include "content/public/browser/cookie_store_factory.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" -#include "net/base/cache_type.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_known_logs.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_policy_enforcer.h" -#include "net/cert/multi_log_ct_verifier.h" -#include "net/dns/host_resolver.h" -#include "net/dns/mapped_host_resolver.h" -#include "net/extras/sqlite/sqlite_channel_id_store.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_auth_preferences.h" -#include "net/http/http_auth_scheme.h" -#include "net/http/http_cache.h" -#include "net/http/http_server_properties_impl.h" -#include "net/http/transport_security_persister.h" -#include "net/proxy/proxy_script_fetcher_impl.h" -#include "net/proxy/proxy_service.h" -#include "net/ssl/channel_id_service.h" -#include "net/ssl/default_channel_id_store.h" -#include "net/ssl/ssl_config_service_defaults.h" -#include "net/url_request/static_http_user_agent_settings.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/file_protocol_handler.h" -#include "net/url_request/ftp_protocol_handler.h" -#include "net/url_request/url_request_intercepting_job_factory.h" -#include "net/ftp/ftp_network_layer.h" - -#include "api/qwebengineurlschemehandler.h" -#include "browser_context_qt.h" -#include "custom_protocol_handler.h" -#include "proxy_config_service_qt.h" -#include "qrc_protocol_handler_qt.h" -#include "qwebenginecookiestore.h" -#include "qwebenginecookiestore_p.h" -#include "type_conversion.h" +#include "profile_io_data_qt.h" namespace QtWebEngineCore { -using content::BrowserThread; - -URLRequestContextGetterQt::URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors) - : m_ignoreCertificateErrors(false) - , m_mutex(QMutex::Recursive) - , m_contextInitialized(false) - , m_updateAllStorage(false) - , m_updateCookieStore(false) - , m_updateHttpCache(false) - , m_updateJobFactory(true) - , m_updateUserAgent(false) - , m_browserContext(browserContext) - , m_baseJobFactory(0) - , m_cookieDelegate(new CookieMonsterDelegateQt()) - , m_requestInterceptors(std::move(request_interceptors)) +URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data) + : m_profileIOData(data) { - std::swap(m_protocolHandlers, *protocolHandlers); - - // The ProtocolHandlerRegistry and it's JobInterceptorFactory need to be - // created on the UI thread: - ProtocolHandlerRegistry* protocolHandlerRegistry = - ProtocolHandlerRegistryFactory::GetForBrowserContext(browserContext->browserContext()); - DCHECK(protocolHandlerRegistry); - m_protocolHandlerInterceptor = - protocolHandlerRegistry->CreateJobInterceptorFactory(); - - QMutexLocker lock(&m_mutex); - m_cookieDelegate->setClient(browserContext->cookieStore()); - setFullConfiguration(browserContext); - updateStorageSettings(); } URLRequestContextGetterQt::~URLRequestContextGetterQt() { - m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted - delete m_proxyConfigService.fetchAndStoreAcquire(0); -} - - -void URLRequestContextGetterQt::setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext) -{ - if (!browserContext) - return; - - m_requestInterceptor = browserContext->requestInterceptor(); - m_persistentCookiesPolicy = browserContext->persistentCookiesPolicy(); - m_cookiesPath = browserContext->cookiesPath(); - m_channelIdPath = browserContext->channelIdPath(); - m_httpAcceptLanguage = browserContext->httpAcceptLanguage(); - m_httpUserAgent = browserContext->httpUserAgent(); - m_httpCacheType = browserContext->httpCacheType(); - m_httpCachePath = browserContext->httpCachePath(); - m_httpCacheMaxSize = browserContext->httpCacheMaxSize(); - m_customUrlSchemes = browserContext->customUrlSchemes(); - m_dataPath = browserContext->dataPath(); } net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - if (!m_urlRequestContext) { - m_urlRequestContext.reset(new net::URLRequestContext()); - - m_networkDelegate.reset(new NetworkDelegateQt(this)); - m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); - m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding)); - - QMutexLocker lock(&m_mutex); - generateAllStorage(); - generateJobFactory(); - m_contextInitialized = true; - } - - return m_urlRequestContext.get(); -} - -void URLRequestContextGetterQt::updateStorageSettings() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - QMutexLocker lock(&m_mutex); - setFullConfiguration(m_browserContext.toStrongRef()); - - if (!m_updateAllStorage) { - m_updateAllStorage = true; - // We must create the proxy config service on the UI loop on Linux because it - // must synchronously run on the glib message loop. This will be passed to - // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). - Q_ASSERT(m_proxyConfigService == 0); - m_proxyConfigService = - new ProxyConfigServiceQt( - net::ProxyService::CreateSystemProxyConfigService( - content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); - //pass interface to io thread - m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface(); - - if (m_contextInitialized) - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextGetterQt::generateAllStorage, this)); - } -} - -void URLRequestContextGetterQt::cancelAllUrlRequests() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests(); - std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); - std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); - for ( ; it != end; ++it) { - net::URLRequest* request = const_cast<net::URLRequest*>(*it); - if (request) - request->Cancel(); - } - -} - -void URLRequestContextGetterQt::generateAllStorage() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - QMutexLocker lock(&m_mutex); - generateStorage(); - generateCookieStore(); - generateUserAgent(); - generateHttpCache(); - m_updateAllStorage = false; -} - -static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme, - net::kDigestAuthScheme, -#if defined(USE_KERBEROS) && !defined(OS_ANDROID) - net::kNegotiateAuthScheme, -#endif - net::kNtlmAuthScheme }; - -void URLRequestContextGetterQt::generateStorage() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - - // We must stop all requests before deleting their backends. - if (m_storage) { - m_cookieDelegate->setCookieMonster(0); - m_storage->set_cookie_store(0); - cancelAllUrlRequests(); - // we need to get rid of dangling pointer due to coming storage deletion - m_urlRequestContext->set_http_transaction_factory(0); - m_httpNetworkSession.reset(); - m_transportSecurityPersister.reset(); - } - - - m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); - - net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); - Q_ASSERT(proxyConfigService); - - m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); - std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); - ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); - m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::CTPolicyEnforcer)); - - std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); - - // The System Proxy Resolver has issues on Windows with unconfigured network cards, - // which is why we want to use the v8 one - if (!m_dhcpProxyScriptFetcherFactory) - m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory); - - proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); - m_storage->set_proxy_service(content::CreateProxyServiceUsingMojoFactory( - std::move(proxyResolver), - std::unique_ptr<net::ProxyConfigService>(proxyConfigService), - std::make_unique<net::ProxyScriptFetcherImpl>(m_urlRequestContext.get()), - m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()), - host_resolver.get(), - nullptr /* NetLog */, - m_networkDelegate.get())); - - m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); - m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>()); - - if (!m_dataPath.isEmpty()) { - scoped_refptr<base::SequencedTaskRunner> background_task_runner( - base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), - base::TaskPriority::BACKGROUND, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})); - m_transportSecurityPersister = - std::make_unique<net::TransportSecurityPersister>( - m_urlRequestContext->transport_security_state(), - toFilePath(m_dataPath), - background_task_runner); - } - - if (!m_httpAuthPreferences) { - std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes)); - m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types -#if defined(OS_POSIX) && !defined(OS_ANDROID) - , std::string() /* gssapi library name */ -#endif - )); - } - m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(), host_resolver.get())); - m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); - - // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. - m_storage->set_host_resolver(std::move(host_resolver)); -} - -void URLRequestContextGetterQt::updateCookieStore() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); - m_persistentCookiesPolicy = m_browserContext.data()->persistentCookiesPolicy(); - m_cookiesPath = m_browserContext.data()->cookiesPath(); - m_channelIdPath = m_browserContext.data()->channelIdPath(); - - if (m_contextInitialized && !m_updateAllStorage && !m_updateCookieStore) { - m_updateCookieStore = true; - m_updateHttpCache = true; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextGetterQt::generateCookieStore, this)); - } -} - -void URLRequestContextGetterQt::generateCookieStore() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - QMutexLocker lock(&m_mutex); - m_updateCookieStore = false; - - scoped_refptr<net::SQLiteChannelIDStore> channel_id_db; - if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != BrowserContextAdapter::NoPersistentCookies) { - channel_id_db = new net::SQLiteChannelIDStore( - toFilePath(m_channelIdPath), - base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BACKGROUND})); - } - - m_storage->set_channel_id_service( - base::WrapUnique(new net::ChannelIDService( - new net::DefaultChannelIDStore(channel_id_db.get())))); - - // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file. - m_cookieDelegate->setCookieMonster(0); - m_storage->set_cookie_store(0); - - std::unique_ptr<net::CookieStore> cookieStore; - switch (m_persistentCookiesPolicy) { - case BrowserContextAdapter::NoPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - base::FilePath(), - false, - false, - nullptr) - ); - break; - case BrowserContextAdapter::AllowPersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - false, - true, - nullptr) - ); - break; - case BrowserContextAdapter::ForcePersistentCookies: - cookieStore = content::CreateCookieStore( - content::CookieStoreConfig( - toFilePath(m_cookiesPath), - true, - true, - nullptr) - ); - break; - } - - net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get()); - cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID()); - m_cookieDelegate->setCookieMonster(cookieMonster); - m_storage->set_cookie_store(std::move(cookieStore)); - - const std::vector<std::string> cookieableSchemes(kCookieableSchemes, kCookieableSchemes + arraysize(kCookieableSchemes)); - cookieMonster->SetCookieableSchemes(cookieableSchemes); - - if (!m_updateAllStorage && m_updateHttpCache) { - // HttpCache needs to be regenerated when we generate a new channel id service - generateHttpCache(); - } -} - -void URLRequestContextGetterQt::updateUserAgent() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); - m_httpAcceptLanguage = m_browserContext.data()->httpAcceptLanguage(); - m_httpUserAgent = m_browserContext.data()->httpUserAgent(); - - if (m_contextInitialized && !m_updateAllStorage && !m_updateUserAgent) { - m_updateUserAgent = true; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); - } -} - -void URLRequestContextGetterQt::generateUserAgent() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - QMutexLocker lock(&m_mutex); - m_updateUserAgent = false; - - m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( - new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString()))); -} - -void URLRequestContextGetterQt::updateHttpCache() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); - m_httpCacheType = m_browserContext.data()->httpCacheType(); - m_httpCachePath = m_browserContext.data()->httpCachePath(); - m_httpCacheMaxSize = m_browserContext.data()->httpCacheMaxSize(); - - if (m_httpCacheType == BrowserContextAdapter::NoCache) { - content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_browserContext.data()->browserContext()); - remover->Remove(base::Time(), base::Time::Max(), - content::BrowsingDataRemover::DATA_TYPE_CACHE, - content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); - } - - if (m_contextInitialized && !m_updateAllStorage && !m_updateHttpCache) { - m_updateHttpCache = true; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextGetterQt::generateHttpCache, this)); - } -} - -void URLRequestContextGetterQt::updateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); - m_customUrlSchemes = m_browserContext.data()->customUrlSchemes(); - - if (m_contextInitialized && !m_updateJobFactory) { - m_updateJobFactory = true; - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextGetterQt::regenerateJobFactory, this)); - } -} - -void URLRequestContextGetterQt::updateRequestInterceptor() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); - m_requestInterceptor = m_browserContext.data()->requestInterceptor(); - - // We in this case do not need to regenerate any Chromium classes. -} - -static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, const net::HttpNetworkSession::Context &second) -{ - if (first.transport_security_state != second.transport_security_state) - return false; - if (first.cert_verifier != second.cert_verifier) - return false; - if (first.channel_id_service != second.channel_id_service) - return false; - if (first.proxy_service != second.proxy_service) - return false; - if (first.ssl_config_service != second.ssl_config_service) - return false; - if (first.http_auth_handler_factory != second.http_auth_handler_factory) - return false; - if (first.http_server_properties != second.http_server_properties) - return false; - if (first.host_resolver != second.host_resolver) - return false; - if (first.cert_transparency_verifier != second.cert_transparency_verifier) - return false; - if (first.ct_policy_enforcer != second.ct_policy_enforcer) - return false; - - return true; -} - -static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second) -{ - if (first.ignore_certificate_errors != second.ignore_certificate_errors) - return false; - - return true; -} - -net::HttpNetworkSession::Context URLRequestContextGetterQt::generateNetworkSessionContext() -{ - Q_ASSERT(m_urlRequestContext); - - net::HttpNetworkSession::Context network_session_context; - - network_session_context.transport_security_state = m_urlRequestContext->transport_security_state(); - network_session_context.cert_verifier = m_urlRequestContext->cert_verifier(); - network_session_context.channel_id_service = m_urlRequestContext->channel_id_service(); - network_session_context.proxy_service = m_urlRequestContext->proxy_service(); - network_session_context.ssl_config_service = m_urlRequestContext->ssl_config_service(); - network_session_context.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory(); - network_session_context.http_server_properties = m_urlRequestContext->http_server_properties(); - network_session_context.host_resolver = m_urlRequestContext->host_resolver(); - network_session_context.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier(); - network_session_context.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer(); - - return network_session_context; -} - -net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessionParams() -{ - Q_ASSERT(m_urlRequestContext); - - net::HttpNetworkSession::Params network_session_params; - - network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors; - - return network_session_params; -} - -void URLRequestContextGetterQt::generateHttpCache() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_storage); - - QMutexLocker lock(&m_mutex); - m_updateHttpCache = false; - - if (m_updateCookieStore) - generateCookieStore(); - - net::HttpCache::DefaultBackend* main_backend = 0; - switch (m_httpCacheType) { - case BrowserContextAdapter::MemoryHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::MEMORY_CACHE, - net::CACHE_BACKEND_DEFAULT, - base::FilePath(), - m_httpCacheMaxSize - ); - break; - case BrowserContextAdapter::DiskHttpCache: - main_backend = - new net::HttpCache::DefaultBackend( - net::DISK_CACHE, - net::CACHE_BACKEND_DEFAULT, - toFilePath(m_httpCachePath), - m_httpCacheMaxSize - ); - break; - case BrowserContextAdapter::NoCache: - // It's safe to not create BackendFactory. - break; - } - - net::HttpCache *cache = 0; - net::HttpNetworkSession::Context network_session_context = generateNetworkSessionContext(); - net::HttpNetworkSession::Params network_session_params = generateNetworkSessionParams(); - - if (!m_httpNetworkSession - || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) - || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { - cancelAllUrlRequests(); - m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, network_session_context)); - } - - cache = new net::HttpCache(m_httpNetworkSession.get(), std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false); - - m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); -} - -void URLRequestContextGetterQt::generateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(!m_jobFactory); - - QMutexLocker lock(&m_mutex); - m_updateJobFactory = false; - - std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); - for (auto &it : m_protocolHandlers) - jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release())); - m_protocolHandlers.clear(); - - jobFactory->SetProtocolHandler(url::kDataScheme, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler())); - jobFactory->SetProtocolHandler(url::kFileScheme, - std::make_unique<net::FileProtocolHandler>( - base::CreateTaskRunnerWithTraits({base::MayBlock(), - base::TaskPriority::BACKGROUND, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))); - jobFactory->SetProtocolHandler(kQrcSchemeQt, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt())); - jobFactory->SetProtocolHandler(url::kFtpScheme, - net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver())); - - m_installedCustomSchemes = m_customUrlSchemes; - Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { - jobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); - } - - m_baseJobFactory = jobFactory.get(); - - // Set up interceptors in the reverse order. - std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); - - for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { - topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::move(*i))); - } - - m_requestInterceptors.clear(); - - if (m_protocolHandlerInterceptor) { - m_protocolHandlerInterceptor->Chain(std::move(topJobFactory)); - topJobFactory = std::move(m_protocolHandlerInterceptor); - } - - m_jobFactory = std::move(topJobFactory); - - m_urlRequestContext->set_job_factory(m_jobFactory.get()); -} - -void URLRequestContextGetterQt::regenerateJobFactory() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_urlRequestContext); - Q_ASSERT(m_jobFactory); - Q_ASSERT(m_baseJobFactory); - - QMutexLocker lock(&m_mutex); - m_updateJobFactory = false; - - if (m_customUrlSchemes == m_installedCustomSchemes) - return; - - Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); - } - - m_installedCustomSchemes = m_customUrlSchemes; - Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { - m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); - } + return m_profileIOData->urlRequestContext(); } scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const diff --git a/src/core/net/url_request_context_getter_qt.h b/src/core/net/url_request_context_getter_qt.h index 0e4e84b4a..b6135cb16 100644 --- a/src/core/net/url_request_context_getter_qt.h +++ b/src/core/net/url_request_context_getter_qt.h @@ -42,110 +42,18 @@ #include "net/url_request/url_request_context_getter.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "chrome/browser/custom_handlers/protocol_handler_registry.h" -#include "net/http/http_network_session.h" -#include "net/url_request/url_request_context_storage.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "net/proxy/dhcp_proxy_script_fetcher_factory.h" -#include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h" - -#include "cookie_monster_delegate_qt.h" -#include "network_delegate_qt.h" -#include "browser_context_adapter.h" - -#include <QtCore/qatomic.h> -#include <QtCore/qmutex.h> -#include <QtCore/qsharedpointer.h> - -namespace net { -class HttpAuthPreferences; -class MappedHostResolver; -class ProxyConfigService; -class TransportSecurityPersister; -} - namespace QtWebEngineCore { -// FIXME: This class should be split into a URLRequestContextGetter and a ProfileIOData, similar to what chrome does. +class ProfileIODataQt; + class URLRequestContextGetterQt : public net::URLRequestContextGetter { public: - URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors); - + URLRequestContextGetterQt(ProfileIODataQt *data); net::URLRequestContext *GetURLRequestContext() override; scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; - - // Called on the UI thread: - void updateStorageSettings(); - void updateUserAgent(); - void updateCookieStore(); - void updateHttpCache(); - void updateJobFactory(); - void updateRequestInterceptor(); - private: virtual ~URLRequestContextGetterQt(); - - // Called on the IO thread: - void generateAllStorage(); - void generateStorage(); - void generateCookieStore(); - void generateHttpCache(); - void generateUserAgent(); - void generateJobFactory(); - void regenerateJobFactory(); - void cancelAllUrlRequests(); - net::HttpNetworkSession::Params generateNetworkSessionParams(); - net::HttpNetworkSession::Context generateNetworkSessionContext(); - - void setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext); - - bool m_ignoreCertificateErrors; - - QMutex m_mutex; - bool m_contextInitialized; - bool m_updateAllStorage; - bool m_updateCookieStore; - bool m_updateHttpCache; - bool m_updateJobFactory; - bool m_updateUserAgent; - - QWeakPointer<BrowserContextAdapter> m_browserContext; - content::ProtocolHandlerMap m_protocolHandlers; - - QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; - std::unique_ptr<net::URLRequestContext> m_urlRequestContext; - std::unique_ptr<NetworkDelegateQt> m_networkDelegate; - std::unique_ptr<net::URLRequestContextStorage> m_storage; - std::unique_ptr<net::URLRequestJobFactory> m_jobFactory; - std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> m_protocolHandlerInterceptor; - net::URLRequestJobFactoryImpl *m_baseJobFactory; - std::unique_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory; - scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; - content::URLRequestInterceptorScopedVector m_requestInterceptors; - std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; - std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; - mojo::InterfacePtrInfo<proxy_resolver::mojom::ProxyResolverFactory> m_proxyResolverFactoryInterface; - std::unique_ptr<net::TransportSecurityPersister> m_transportSecurityPersister; - - QList<QByteArray> m_installedCustomSchemes; - QWebEngineUrlRequestInterceptor* m_requestInterceptor; - - // Configuration values to setup URLRequestContext in IO thread, copied from browserContext - // FIXME: Should later be moved to a separate ProfileIOData class. - BrowserContextAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; - QString m_cookiesPath; - QString m_channelIdPath; - QString m_httpAcceptLanguage; - QString m_httpUserAgent; - BrowserContextAdapter::HttpCacheType m_httpCacheType; - QString m_httpCachePath; - int m_httpCacheMaxSize; - QList<QByteArray> m_customUrlSchemes; - QString m_dataPath; - - friend class NetworkDelegateQt; + ProfileIODataQt *m_profileIOData; }; } // namespace QtWebEngineCore diff --git a/src/core/net/url_request_custom_job.cpp b/src/core/net/url_request_custom_job.cpp index cf96cd6d9..ecfa8e17a 100644 --- a/src/core/net/url_request_custom_job.cpp +++ b/src/core/net/url_request_custom_job.cpp @@ -51,9 +51,9 @@ namespace QtWebEngineCore { URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, const std::string &scheme, - QWeakPointer<const BrowserContextAdapter> adapter) + QPointer<ProfileAdapter> profileAdapter) : URLRequestJob(request, networkDelegate) - , m_proxy(new URLRequestCustomJobProxy(this, scheme, adapter)) + , m_proxy(new URLRequestCustomJobProxy(this, scheme, profileAdapter)) , m_device(nullptr) , m_error(0) , m_pendingReadSize(0) @@ -119,7 +119,7 @@ bool URLRequestCustomJob::GetCharset(std::string* charset) return false; } -bool URLRequestCustomJob::IsRedirectResponse(GURL* location, int* http_status_code) +bool URLRequestCustomJob::IsRedirectResponse(GURL* location, int* http_status_code, bool* /*insecure_scheme_was_upgraded*/) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (m_redirect.is_valid()) { diff --git a/src/core/net/url_request_custom_job.h b/src/core/net/url_request_custom_job.h index 021cf3204..16be76f29 100644 --- a/src/core/net/url_request_custom_job.h +++ b/src/core/net/url_request_custom_job.h @@ -42,13 +42,13 @@ #include "net/url_request/url_request_job.h" #include "url/gurl.h" -#include <QtCore/QWeakPointer> +#include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class URLRequestCustomJobDelegate; class URLRequestCustomJobProxy; @@ -58,13 +58,13 @@ public: URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, const std::string &scheme, - QWeakPointer<const BrowserContextAdapter> adapter); + QPointer<ProfileAdapter> profileAdapter); void Start() override; void Kill() override; int ReadRawData(net::IOBuffer *buf, int buf_size) override; bool GetMimeType(std::string *mimeType) const override; bool GetCharset(std::string *charset) override; - bool IsRedirectResponse(GURL* location, int* http_status_code) override; + bool IsRedirectResponse(GURL* location, int* http_status_code, bool* insecure_scheme_was_upgraded) override; protected: virtual ~URLRequestCustomJob(); diff --git a/src/core/net/url_request_custom_job_delegate.h b/src/core/net/url_request_custom_job_delegate.h index 6bbd10909..caabfcf99 100644 --- a/src/core/net/url_request_custom_job_delegate.h +++ b/src/core/net/url_request_custom_job_delegate.h @@ -37,11 +37,22 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ #define URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ #include "base/memory/ref_counted.h" -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QObject> #include <QUrl> @@ -52,7 +63,7 @@ namespace QtWebEngineCore { class URLRequestCustomJobProxy; -class QWEBENGINE_EXPORT URLRequestCustomJobDelegate : public QObject { +class QWEBENGINECORE_PRIVATE_EXPORT URLRequestCustomJobDelegate : public QObject { Q_OBJECT public: ~URLRequestCustomJobDelegate(); diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index 526ac2f8b..b5f10388c 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -41,9 +41,10 @@ #include "url_request_custom_job.h" #include "url_request_custom_job_delegate.h" #include "api/qwebengineurlrequestjob.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "type_conversion.h" #include "content/public/browser/browser_thread.h" +#include "web_engine_context.h" using namespace net; @@ -51,12 +52,12 @@ namespace QtWebEngineCore { URLRequestCustomJobProxy::URLRequestCustomJobProxy(URLRequestCustomJob *job, const std::string &scheme, - QWeakPointer<const BrowserContextAdapter> adapter) + QPointer<ProfileAdapter> profileAdapter) : m_job(job) , m_started(false) , m_scheme(scheme) , m_delegate(nullptr) - , m_adapter(adapter) + , m_profileAdapter(profileAdapter) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); } @@ -160,10 +161,11 @@ void URLRequestCustomJobProxy::initialize(GURL url, std::string method, base::Op if (initiator.has_value()) initiatorOrigin = QUrl::fromEncoded(QByteArray::fromStdString(initiator.value().Serialize())); - QWebEngineUrlSchemeHandler *schemeHandler = 0; - QSharedPointer<const BrowserContextAdapter> browserContext = m_adapter.toStrongRef(); - if (browserContext) - schemeHandler = browserContext->customUrlSchemeHandlers()[toQByteArray(m_scheme)]; + QWebEngineUrlSchemeHandler *schemeHandler = nullptr; + + if (m_profileAdapter) + schemeHandler = m_profileAdapter->customUrlSchemeHandlers()[toQByteArray(m_scheme)]; + if (schemeHandler) { m_delegate = new URLRequestCustomJobDelegate(this, toQt(url), QByteArray::fromStdString(method), diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h index 603ad5840..3986fe119 100644 --- a/src/core/net/url_request_custom_job_proxy.h +++ b/src/core/net/url_request_custom_job_proxy.h @@ -44,7 +44,7 @@ #include "base/optional.h" #include "url/gurl.h" #include "url/origin.h" -#include <QtCore/QWeakPointer> +#include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) @@ -52,7 +52,7 @@ namespace QtWebEngineCore { class URLRequestCustomJob; class URLRequestCustomJobDelegate; -class BrowserContextAdapter; +class ProfileAdapter; // Used to comunicate between URLRequestCustomJob living on the IO thread // and URLRequestCustomJobDelegate living on the UI thread. @@ -62,7 +62,7 @@ class URLRequestCustomJobProxy public: URLRequestCustomJobProxy(URLRequestCustomJob *job, const std::string &scheme, - QWeakPointer<const BrowserContextAdapter> adapter); + QPointer<ProfileAdapter> profileAdapter); ~URLRequestCustomJobProxy(); // Called from URLRequestCustomJobDelegate via post: @@ -82,7 +82,7 @@ public: // UI thread owned: std::string m_scheme; URLRequestCustomJobDelegate *m_delegate; - QWeakPointer<const BrowserContextAdapter> m_adapter; + QPointer<ProfileAdapter> m_profileAdapter; }; } // namespace QtWebEngineCore diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp index 3b13f03b8..918500b58 100644 --- a/src/core/net/webui_controller_factory_qt.cpp +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -57,10 +57,10 @@ #include "content/public/browser/web_ui.h" #include "content/public/common/content_client.h" #include "content/public/common/url_utils.h" -#include "extensions/features/features.h" -#include "media/media_features.h" -#include "ppapi/features/features.h" -#include "printing/features/features.h" +#include "extensions/buildflags/buildflags.h" +#include "media/media_buildflags.h" +#include "ppapi/buildflags/buildflags.h" +#include "printing/buildflags/buildflags.h" #include "ui/web_dialogs/web_dialog_ui.h" #include "url/gurl.h" @@ -105,13 +105,13 @@ namespace { // A function for creating a new WebUI. The caller owns the return value, which // may be NULL (for example, if the URL refers to an non-existent extension). -typedef WebUIController* (*WebUIFactoryFunction)(WebUI *web_ui, const GURL &url); +typedef std::unique_ptr<WebUIController> (*WebUIFactoryFunction)(WebUI *web_ui, const GURL &url); // Template for defining WebUIFactoryFunction. template<class T> -WebUIController *NewWebUI(WebUI *web_ui, const GURL &/*url*/) +std::unique_ptr<WebUIController> NewWebUI(WebUI *web_ui, const GURL &/*url*/) { - return new T(web_ui); + return std::unique_ptr<WebUIController>(new T(web_ui)); } // Returns a function that can be used to create the right type of WebUI for a @@ -192,7 +192,7 @@ bool WebUIControllerFactoryQt::UseWebUIBindingsForURL(content::BrowserContext *b return UseWebUIForURL(browser_context, url); } -WebUIController *WebUIControllerFactoryQt::CreateWebUIControllerForURL(WebUI *web_ui, const GURL &url) const +std::unique_ptr<WebUIController> WebUIControllerFactoryQt::CreateWebUIControllerForURL(WebUI *web_ui, const GURL &url) const { Profile *profile = Profile::FromWebUI(web_ui); WebUIFactoryFunction function = GetWebUIFactoryFunction(web_ui, profile, url); diff --git a/src/core/net/webui_controller_factory_qt.h b/src/core/net/webui_controller_factory_qt.h index 440dd5a13..4038e6538 100644 --- a/src/core/net/webui_controller_factory_qt.h +++ b/src/core/net/webui_controller_factory_qt.h @@ -60,7 +60,7 @@ public: content::WebUI::TypeID GetWebUIType(content::BrowserContext *browserContext, const GURL &url) const override; bool UseWebUIForURL(content::BrowserContext *browserContext, const GURL &url) const override; bool UseWebUIBindingsForURL(content::BrowserContext *browserContext, const GURL &url) const override; - content::WebUIController *CreateWebUIControllerForURL(content::WebUI *webUi, const GURL &url) const override; + std::unique_ptr<content::WebUIController> CreateWebUIControllerForURL(content::WebUI *webUi, const GURL &url) const override; static WebUIControllerFactoryQt *GetInstance(); diff --git a/src/core/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 954917094..1850380a2 100644 --- a/src/core/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -46,10 +46,6 @@ #include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_implementation.h" -#if defined(USE_X11) -#include <X11/Xlib.h> -#endif - #if defined(OS_WIN) #include "ui/gl/gl_context_wgl.h" #endif @@ -116,7 +112,7 @@ void* GLContextHelper::getEGLConfig() return resourceForContext(resource); } -void* GLContextHelper::getXConfig() +void* GLContextHelper::getGlXConfig() { return resourceForContext(QByteArrayLiteral("glxconfig")); } @@ -128,15 +124,8 @@ void* GLContextHelper::getEGLDisplay() void* GLContextHelper::getXDisplay() { - void *display = qApp->platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("display"), qApp->primaryScreen()); -#if defined(USE_X11) - if (!display) { - // XLib isn't available or has not been initialized, which is a decision we wish to - // support, for example for the GPU process. - display = XOpenDisplay(NULL); - } -#endif - return display; + return qApp->platformNativeInterface()->nativeResourceForScreen( + QByteArrayLiteral("display"), qApp->primaryScreen()); } void* GLContextHelper::getNativeDisplay() @@ -168,17 +157,14 @@ QFunctionPointer GLContextHelper::getEglGetProcAddress() QT_END_NAMESPACE -#if defined(USE_OZONE) || defined(OS_WIN) - +#if defined(OS_WIN) namespace gl { - namespace init { scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group, GLSurface* compatible_surface, const GLContextAttribs& attribs) { -#if defined(OS_WIN) scoped_refptr<GLContext> context; if (GetGLImplementation() == kGLImplementationDesktopGL) { context = new GLContextWGL(share_group); @@ -188,18 +174,14 @@ scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group, } else { context = new GLContextEGL(share_group); } -#else - scoped_refptr<GLContext> context = new GLContextEGL(share_group); -#endif if (!GLContextHelper::initializeContext(context.get(), compatible_surface, attribs)) - return NULL; + return nullptr; return context; } } // namespace init - } // namespace gl -#endif // defined(USE_OZONE) || defined(OS_WIN) +#endif // defined(OS_WIN) diff --git a/src/core/gl_context_qt.h b/src/core/ozone/gl_context_qt.h index cecceabc9..59ee567aa 100644 --- a/src/core/gl_context_qt.h +++ b/src/core/ozone/gl_context_qt.h @@ -58,7 +58,7 @@ public: static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static void* getEGLConfig(); - static void* getXConfig(); + static void* getGlXConfig(); static void* getEGLDisplay(); static void* getXDisplay(); static void* getNativeDisplay(); diff --git a/src/core/ozone/gl_ozone_egl_qt.cpp b/src/core/ozone/gl_ozone_egl_qt.cpp index a9b3da5e2..2fa86d79b 100644 --- a/src/core/ozone/gl_ozone_egl_qt.cpp +++ b/src/core/ozone/gl_ozone_egl_qt.cpp @@ -38,11 +38,13 @@ ****************************************************************************/ #if defined(USE_OZONE) - +#include "gl_ozone_egl_qt.h" +#include "gl_context_qt.h" +#include "gl_surface_egl_qt.h" #include "base/files/file_path.h" #include "base/native_library.h" #include "gl_context_qt.h" -#include "ozone/gl_ozone_egl_qt.h" +#include "gl_ozone_egl_qt.h" #include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" @@ -53,12 +55,16 @@ #include <EGL/egl.h> #include <dlfcn.h> +#include <QtGui/qtgui-config.h> // for QT_NO_OPENGL + #ifndef QT_NO_OPENGL #include <QOpenGLContext> +QT_BEGIN_NAMESPACE Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +QT_END_NAMESPACE #endif -namespace QtWebEngineCore { +namespace ui { base::NativeLibrary LoadLibrary(const base::FilePath& filename) { base::NativeLibraryLoadError error; @@ -103,6 +109,39 @@ bool GLOzoneEGLQt::LoadGLES2Bindings(gl::GLImplementation /*implementation*/) return true; } +bool GLOzoneEGLQt::InitializeGLOneOffPlatform() +{ + if (!gl::GLSurfaceEGLQt::InitializeOneOff()) { + LOG(ERROR) << "GLOzoneEGLQt::InitializeOneOff failed."; + return false; + } + return true; +} + +bool GLOzoneEGLQt::InitializeExtensionSettingsOneOffPlatform() +{ + return gl::GLSurfaceEGLQt::InitializeExtensionSettingsOneOff(); +} + +scoped_refptr<gl::GLSurface> GLOzoneEGLQt::CreateViewGLSurface(gfx::AcceleratedWidget window) +{ + return nullptr; +} + +scoped_refptr<gl::GLSurface> GLOzoneEGLQt::CreateOffscreenGLSurface(const gfx::Size &size) +{ + scoped_refptr<gl::GLSurface> surface = new gl::GLSurfaceEGLQt(size); + if (surface->Initialize(gl::GLSurfaceFormat())) + return surface; + + surface = new gl::GLSurfacelessQtEGL(size); + if (surface->Initialize(gl::GLSurfaceFormat())) + return surface; + + LOG(WARNING) << "Failed to create offscreen GL surface"; + return nullptr; +} + intptr_t GLOzoneEGLQt::GetNativeDisplay() { static void *display = GLContextHelper::getNativeDisplay(); @@ -113,6 +152,6 @@ intptr_t GLOzoneEGLQt::GetNativeDisplay() return reinterpret_cast<intptr_t>(EGL_DEFAULT_DISPLAY); } -} // namespace QtWebEngineCore +} // namespace ui #endif // defined(USE_OZONE) diff --git a/src/core/ozone/gl_ozone_egl_qt.h b/src/core/ozone/gl_ozone_egl_qt.h index fc609c51c..c24d03a81 100644 --- a/src/core/ozone/gl_ozone_egl_qt.h +++ b/src/core/ozone/gl_ozone_egl_qt.h @@ -44,18 +44,16 @@ #include "ui/ozone/common/gl_ozone_egl.h" -namespace QtWebEngineCore { +namespace ui { -class GLOzoneEGLQt : public ui::GLOzoneEGL { +class GLOzoneEGLQt : public GLOzoneEGL { public: - scoped_refptr<gl::GLSurface> CreateViewGLSurface(gfx::AcceleratedWidget /*window*/) override - { - return nullptr; - } - scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(const gfx::Size& /*size*/) override - { - return nullptr; - } + bool InitializeGLOneOffPlatform() override; + bool InitializeExtensionSettingsOneOffPlatform() override; + scoped_refptr<gl::GLSurface> CreateViewGLSurface( + gfx::AcceleratedWidget window) override; + scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface( + const gfx::Size& size) override; protected: // Returns native platform display handle. This is used to obtain the EGL @@ -66,7 +64,7 @@ protected: bool LoadGLES2Bindings(gl::GLImplementation implementation) override; }; -} // namespace QtWebEngineCore +} // namespace ui #endif // defined(USE_OZONE) diff --git a/src/core/ozone/gl_ozone_glx_qt.cpp b/src/core/ozone/gl_ozone_glx_qt.cpp new file mode 100644 index 000000000..9a0fea7c7 --- /dev/null +++ b/src/core/ozone/gl_ozone_glx_qt.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "gl_ozone_glx_qt.h" +#include "gl_surface_glx_qt.h" +#include "ui/gl/gl_context_glx.h" +#include "ui/gl/gl_gl_api_implementation.h" +#include "ui/gl/gl_glx_api_implementation.h" +#include <dlfcn.h> + +namespace ui { + +bool GLOzoneGLXQt::InitializeGLOneOffPlatform() { + if (!gl::GLSurfaceGLXQt::InitializeOneOff()) { + LOG(ERROR) << "GLSurfaceGLXQt::InitializeOneOff failed."; + return false; + } + return true; +} + +bool GLOzoneGLXQt::InitializeStaticGLBindings( + gl::GLImplementation implementation) { + + base::NativeLibrary library = dlopen(NULL, RTLD_LAZY); + if (!library) { + LOG(ERROR) << "Failed to open GL context " << dlerror(); + return false; + } + + gl::GLGetProcAddressProc get_proc_address = + reinterpret_cast<gl::GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary(library, + "glXGetProcAddress")); + if (!get_proc_address) { + LOG(ERROR) << "glxGetProcAddress not found."; + base::UnloadNativeLibrary(library); + return false; + } + + gl::SetGLGetProcAddressProc(get_proc_address); + gl::AddGLNativeLibrary(library); + gl::SetGLImplementation(gl::kGLImplementationDesktopGL); + + gl::InitializeStaticGLBindingsGL(); + gl::InitializeStaticGLBindingsGLX(); + + return true; +} + +void GLOzoneGLXQt::InitializeDebugGLBindings() { + gl::InitializeDebugGLBindingsGL(); + gl::InitializeDebugGLBindingsGLX(); +} + +void GLOzoneGLXQt::SetDisabledExtensionsPlatform( + const std::string& disabled_extensions) { + gl::SetDisabledExtensionsGLX(disabled_extensions); +} + +void GLOzoneGLXQt::ShutdownGL() { + gl::ClearBindingsGL(); + gl::ClearBindingsGLX(); +} + +bool GLOzoneGLXQt::GetGLWindowSystemBindingInfo( + gl::GLWindowSystemBindingInfo* info) { + return gl::GetGLWindowSystemBindingInfoGLX(info); +} + +scoped_refptr<gl::GLContext> GLOzoneGLXQt::CreateGLContext( + gl::GLShareGroup* share_group, + gl::GLSurface* compatible_surface, + const gl::GLContextAttribs& attribs) { + return gl::InitializeGLContext(new gl::GLContextGLX(share_group), + compatible_surface, attribs); +} + +scoped_refptr<gl::GLSurface> GLOzoneGLXQt::CreateViewGLSurface( + gfx::AcceleratedWidget window) { + return nullptr; +} + +scoped_refptr<gl::GLSurface> GLOzoneGLXQt::CreateSurfacelessViewGLSurface( + gfx::AcceleratedWidget window) { + return nullptr; +} + +scoped_refptr<gl::GLSurface> GLOzoneGLXQt::CreateOffscreenGLSurface( + const gfx::Size& size) { + scoped_refptr<gl::GLSurface> surface = new gl::GLSurfaceGLXQt(size); + if (surface->Initialize(gl::GLSurfaceFormat())) + return surface; + LOG(WARNING) << "Failed to create offscreen GL surface"; + return nullptr; +} + +bool GLOzoneGLXQt::InitializeExtensionSettingsOneOffPlatform() +{ + return gl::GLSurfaceGLXQt::InitializeExtensionSettingsOneOff(); +} + +} // namespace ui diff --git a/src/core/ozone/gl_ozone_glx_qt.h b/src/core/ozone/gl_ozone_glx_qt.h new file mode 100644 index 000000000..ffbd60454 --- /dev/null +++ b/src/core/ozone/gl_ozone_glx_qt.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 UI_OZONE_GLX_QT_H_ +#define UI_OZONE_GLX_QT_H + +#include "base/macros.h" +#include "ui/gl/gl_implementation.h" +#include "ui/ozone/public/gl_ozone.h" + +namespace ui { + +class GLOzoneGLXQt : public GLOzone { + +public: + GLOzoneGLXQt() {} + ~GLOzoneGLXQt() override {} + + bool InitializeGLOneOffPlatform() override; + bool InitializeStaticGLBindings(gl::GLImplementation implementation) override; + void InitializeDebugGLBindings() override; + bool InitializeExtensionSettingsOneOffPlatform() override; + void ShutdownGL() override; + void SetDisabledExtensionsPlatform( + const std::string& disabled_extensions) override; + bool GetGLWindowSystemBindingInfo( + gl::GLWindowSystemBindingInfo* info) override; + + scoped_refptr<gl::GLContext> CreateGLContext( + gl::GLShareGroup* share_group, + gl::GLSurface* compatible_surface, + const gl::GLContextAttribs& attribs) override; + + scoped_refptr<gl::GLSurface> CreateViewGLSurface( + gfx::AcceleratedWidget window) override; + + scoped_refptr<gl::GLSurface> CreateSurfacelessViewGLSurface( + gfx::AcceleratedWidget window) override; + + scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface( + const gfx::Size& size) override; + +private: + DISALLOW_COPY_AND_ASSIGN(GLOzoneGLXQt); +}; + +} // namespace ui + +#endif // UI_OZONE_GLX_QT_H diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp index 6de9d20b5..9fe5985ce 100644 --- a/src/core/ozone/gl_surface_egl_qt.cpp +++ b/src/core/ozone/gl_surface_egl_qt.cpp @@ -44,8 +44,8 @@ #include "gl_context_qt.h" #include "ozone/gl_surface_egl_qt.h" -#if !defined(OS_MACOSX) #include "ui/gl/gl_surface_egl.h" +#if !defined(OS_MACOSX) #include "ui/gl/egl_util.h" #include "ui/gl/init/gl_factory.h" @@ -140,7 +140,10 @@ bool GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() { return false; } - +bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() +{ + return GLSurfaceEGLQt::g_egl_surfaceless_context_supported; +} bool GLSurfaceEGL::IsEGLContextPrioritySupported() { return false; @@ -299,6 +302,10 @@ void* GLSurfacelessQtEGL::GetShareHandle() return NULL; } +} // namespace gl +#endif // !defined(OS_MACOSX) + +namespace gl { std::string DriverEGL::GetPlatformExtensions() { EGLDisplay display = GLContextHelper::getEGLDisplay(); @@ -309,6 +316,4 @@ std::string DriverEGL::GetPlatformExtensions() const char* str = g_driver_egl.fn.eglQueryStringFn(display, EGL_EXTENSIONS); return str ? std::string(str) : ""; } - -} // namespace gl -#endif // !defined(OS_MACOSX) +} // namespace gl diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp index 51b0f58b0..eebefa59b 100644 --- a/src/core/ozone/gl_surface_glx_qt.cpp +++ b/src/core/ozone/gl_surface_glx_qt.cpp @@ -41,8 +41,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if defined(USE_X11) - #include "gl_context_qt.h" #include "ozone/gl_surface_glx_qt.h" #include "ui/gl/gl_bindings.h" @@ -126,9 +124,9 @@ bool GLSurfaceGLXQt::InitializeOneOff() return false; } - g_config = GLContextHelper::getXConfig(); + g_config = GLContextHelper::getGlXConfig(); if (!g_config) { - LOG(ERROR) << "GLContextHelper::getXConfig() failed."; + LOG(ERROR) << "GLContextHelper::getGlxConfig() failed."; return false; } @@ -156,7 +154,7 @@ bool GLSurfaceGLXQt::InitializeExtensionSettingsOneOff() Display* display = static_cast<Display*>(g_display); GLSurfaceQt::g_extensions = glXQueryExtensionsString(display, 0); - g_driver_glx.InitializeExtensionBindings(); + g_driver_glx.InitializeExtensionBindings(g_extensions); return true; } @@ -210,4 +208,3 @@ void* GLSurfaceGLXQt::GetHandle() } //namespace gl -#endif // defined(USE_X11) diff --git a/src/core/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index 4d38d7c25..7cde289ae 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -68,13 +68,6 @@ #include "ui/gl/vsync_provider_win.h" #endif -#if defined(USE_X11) -#include "ozone/gl_surface_glx_qt.h" -#include "ui/gl/gl_glx_api_implementation.h" -#include <dlfcn.h> - -#endif - #include "ozone/gl_surface_egl_qt.h" #include "ui/gl/gl_egl_api_implementation.h" @@ -142,13 +135,11 @@ void* GLSurfaceQt::GetConfig() return g_config; } +#if defined(OS_WIN) namespace init { - bool InitializeGLOneOffPlatform() { -#if defined(OS_WIN) VSyncProviderWin::InitializeOneOff(); -#endif if (GetGLImplementation() == kGLImplementationOSMesaGL) return false; @@ -157,12 +148,8 @@ bool InitializeGLOneOffPlatform() return GLSurfaceEGLQt::InitializeOneOff(); if (GetGLImplementation() == kGLImplementationDesktopGL) { -#if defined(OS_WIN) return GLSurfaceWGLQt::InitializeOneOff(); -#elif defined(USE_X11) - if (GLSurfaceGLXQt::InitializeOneOff()) - return true; -#endif + // Fallback to trying EGL with desktop GL. if (GLSurfaceEGLQt::InitializeOneOff()) { g_initializedEGL = true; @@ -173,87 +160,6 @@ bool InitializeGLOneOffPlatform() return false; } -#if defined(USE_X11) -// FIXME: This should be removed when we switch to OZONE only -bool InitializeStaticGLBindings(GLImplementation implementation) { - // Prevent reinitialization with a different implementation. Once the gpu - // unit tests have initialized with kGLImplementationMock, we don't want to - // later switch to another GL implementation. - DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); - base::ThreadRestrictions::ScopedAllowIO allow_io; - - switch (implementation) { - case kGLImplementationOSMesaGL: - return false; - case kGLImplementationDesktopGL: { - base::NativeLibrary library = dlopen(NULL, RTLD_LAZY); - if (!library) { - LOG(ERROR) << "Failed to obtain glx handle" << dlerror(); - return false; - } - - GLGetProcAddressProc get_proc_address = - reinterpret_cast<GLGetProcAddressProc>( - base::GetFunctionPointerFromNativeLibrary(library, - "glXGetProcAddress")); - if (!get_proc_address) { - QFunctionPointer address = GLContextHelper::getGlXGetProcAddress(); - get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(address); - } - if (!get_proc_address) { - LOG(ERROR) << "glxGetProcAddress not found."; - base::UnloadNativeLibrary(library); - return false; - } - - SetGLGetProcAddressProc(get_proc_address); - AddGLNativeLibrary(library); - SetGLImplementation(kGLImplementationDesktopGL); - - InitializeStaticGLBindingsGL(); - InitializeStaticGLBindingsGLX(); - return true; - } - case kGLImplementationSwiftShaderGL: - case kGLImplementationEGLGLES2: { - base::NativeLibrary library = dlopen(NULL, RTLD_LAZY); - if (!library) { - LOG(ERROR) << "Failed to obtain egl handle" << dlerror(); - return false; - } - - GLGetProcAddressProc get_proc_address = - reinterpret_cast<GLGetProcAddressProc>( - base::GetFunctionPointerFromNativeLibrary(library, - "eglGetProcAddress")); - if (!get_proc_address) { - QFunctionPointer address = GLContextHelper::getEglGetProcAddress(); - get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(address); - } - if (!get_proc_address) { - LOG(ERROR) << "eglGetProcAddress not found."; - base::UnloadNativeLibrary(library); - return false; - } - - SetGLGetProcAddressProc(get_proc_address); - AddGLNativeLibrary(library); - SetGLImplementation(kGLImplementationEGLGLES2); - - InitializeStaticGLBindingsGL(); - InitializeStaticGLBindingsEGL(); - return true; - } - case kGLImplementationMockGL: - case kGLImplementationStubGL: - return false; - default: - NOTREACHED(); - } - return false; -} -#endif - bool usingSoftwareDynamicGL() { return QtWebEngineCore::usingSoftwareDynamicGL(); @@ -266,19 +172,10 @@ CreateOffscreenGLSurfaceWithFormat(const gfx::Size& size, GLSurfaceFormat format switch (GetGLImplementation()) { case kGLImplementationDesktopGLCoreProfile: case kGLImplementationDesktopGL: { -#if defined(OS_WIN) surface = new GLSurfaceWGLQt(size); if (surface->Initialize(format)) return surface; break; -#elif defined(USE_X11) - if (!g_initializedEGL) { - surface = new GLSurfaceGLXQt(size); - if (surface->Initialize(format)) - return surface; - } - Q_FALLTHROUGH(); -#endif } case kGLImplementationEGLGLES2: { surface = new GLSurfaceEGLQt(size); @@ -313,8 +210,10 @@ CreateViewGLSurface(gfx::AcceleratedWidget window) } } // namespace init -} // namespace gl +#endif // defined(OS_WIN) +} // namespace gl +#if defined(OS_WIN) namespace gpu { class GpuCommandBufferStub; class GpuChannelManager; @@ -325,11 +224,10 @@ scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeSurface(base::We return scoped_refptr<gl::GLSurface>(); } -#if defined(OS_WIN) bool DirectCompositionSurfaceWin::IsHDRSupported() -{ return false; } -#endif - +{ + return false; +} } // namespace gpu - +#endif #endif // !defined(OS_MACOSX) diff --git a/src/core/gl_surface_qt.h b/src/core/ozone/gl_surface_qt.h index 514527df9..514527df9 100644 --- a/src/core/gl_surface_qt.h +++ b/src/core/ozone/gl_surface_qt.h diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp index 8bb5007ef..905e8f403 100644 --- a/src/core/ozone/ozone_platform_qt.cpp +++ b/src/core/ozone/ozone_platform_qt.cpp @@ -50,6 +50,7 @@ #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/platform_window/platform_window_delegate.h" +#include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/platform_window.h" namespace ui { @@ -64,7 +65,7 @@ public: ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override; ui::CursorFactoryOzone* GetCursorFactoryOzone() override; GpuPlatformSupportHost* GetGpuPlatformSupportHost() override; - std::unique_ptr<PlatformWindow> CreatePlatformWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds) override; + std::unique_ptr<PlatformWindow> CreatePlatformWindow(PlatformWindowDelegate* delegate, PlatformWindowInitProperties properties) override; std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; ui::InputController* GetInputController() override; std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; @@ -104,9 +105,9 @@ GpuPlatformSupportHost* OzonePlatformQt::GetGpuPlatformSupportHost() return gpu_platform_support_host_.get(); } -std::unique_ptr<PlatformWindow> OzonePlatformQt::CreatePlatformWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds) +std::unique_ptr<PlatformWindow> OzonePlatformQt::CreatePlatformWindow(PlatformWindowDelegate* delegate, PlatformWindowInitProperties properties) { - return base::WrapUnique(new PlatformWindowQt(delegate, bounds)); + return base::WrapUnique(new PlatformWindowQt(delegate, properties.bounds)); } ui::InputController* OzonePlatformQt::GetInputController() @@ -145,7 +146,6 @@ void OzonePlatformQt::InitializeGPU(const ui::OzonePlatform::InitParams &) } // namespace - OzonePlatform* CreateOzonePlatformQt() { return new OzonePlatformQt; } gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryQt() diff --git a/src/core/ozone/platform_window_qt.h b/src/core/ozone/platform_window_qt.h index d25096432..b712b706a 100644 --- a/src/core/ozone/platform_window_qt.h +++ b/src/core/ozone/platform_window_qt.h @@ -65,10 +65,12 @@ public: void SetTitle(const base::string16&) override { } void SetCapture() override { } void ReleaseCapture() override { } + bool HasCapture() const override { return false; } void ToggleFullscreen() override { } void Maximize() override { } void Minimize() override { } void Restore() override { } + PlatformWindowState GetPlatformWindowState() const override { return PLATFORM_WINDOW_STATE_UNKNOWN; } void SetCursor(PlatformCursor) override { } void MoveCursorTo(const gfx::Point&) override { } void ConfineCursorToBounds(const gfx::Rect&) override { } diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index f21e14c30..9570852c9 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -37,6 +37,17 @@ ** ****************************************************************************/ +#include "surface_factory_qt.h" +#include "qtwebenginecoreglobal_p.h" +#include "gl_context_qt.h" +#include "gl_ozone_egl_qt.h" +#if QT_CONFIG(webengine_system_x11) +#include "gl_ozone_glx_qt.h" +#endif + +#include "ui/gl/gl_surface.h" +#include <QGuiApplication> + #if defined(USE_OZONE) #include "ozone/gl_ozone_egl_qt.h" @@ -44,16 +55,31 @@ #include "ui/gl/gl_surface.h" namespace QtWebEngineCore { +SurfaceFactoryQt::SurfaceFactoryQt() +{ + Q_ASSERT(qApp); +#if QT_CONFIG(webengine_system_x11) + if (GLContextHelper::getGlXConfig()) { + m_impl = gl::kGLImplementationDesktopGL; + m_ozone.reset(new ui::GLOzoneGLXQt()); + } else +#endif + if (GLContextHelper::getEGLConfig()) { + m_impl = gl::kGLImplementationEGLGLES2; + m_ozone.reset(new ui::GLOzoneEGLQt()); + } else { + qFatal("No suitable graphics backend found\n"); + } +} + std::vector<gl::GLImplementation> SurfaceFactoryQt::GetAllowedGLImplementations() { - std::vector<gl::GLImplementation> impls; - impls.push_back(gl::kGLImplementationEGLGLES2); - return impls; + return { m_impl }; } ui::GLOzone* SurfaceFactoryQt::GetGLOzone(gl::GLImplementation implementation) { - return new GLOzoneEGLQt(); + return m_ozone.get(); } } // namespace QtWebEngineCore diff --git a/src/core/ozone/surface_factory_qt.h b/src/core/ozone/surface_factory_qt.h index b7991829c..dee41d948 100644 --- a/src/core/ozone/surface_factory_qt.h +++ b/src/core/ozone/surface_factory_qt.h @@ -48,8 +48,13 @@ namespace QtWebEngineCore { class SurfaceFactoryQt : public ui::SurfaceFactoryOzone { +public: + SurfaceFactoryQt(); std::vector<gl::GLImplementation> GetAllowedGLImplementations() override; ui::GLOzone* GetGLOzone(gl::GLImplementation implementation) override; +private: + gl::GLImplementation m_impl; + std::unique_ptr<ui::GLOzone> m_ozone; }; } // namespace QtWebEngineCore diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index c65da34af..2fa42bf10 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -40,25 +40,26 @@ #include "permission_manager_qt.h" #include "content/browser/renderer_host/render_view_host_delegate.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/permission_controller.h" #include "content/public/browser/permission_type.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" #include "type_conversion.h" #include "web_contents_delegate_qt.h" namespace QtWebEngineCore { -BrowserContextAdapter::PermissionType toQt(content::PermissionType type) +ProfileAdapter::PermissionType toQt(content::PermissionType type) { switch (type) { case content::PermissionType::GEOLOCATION: - return BrowserContextAdapter::GeolocationPermission; + return ProfileAdapter::GeolocationPermission; case content::PermissionType::AUDIO_CAPTURE: - return BrowserContextAdapter::AudioCapturePermission; + return ProfileAdapter::AudioCapturePermission; case content::PermissionType::VIDEO_CAPTURE: - return BrowserContextAdapter::VideoCapturePermission; + return ProfileAdapter::VideoCapturePermission; case content::PermissionType::FLASH: case content::PermissionType::NOTIFICATIONS: case content::PermissionType::MIDI_SYSEX: @@ -70,10 +71,11 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type) case content::PermissionType::ACCESSIBILITY_EVENTS: case content::PermissionType::CLIPBOARD_READ: case content::PermissionType::CLIPBOARD_WRITE: + case content::PermissionType::PAYMENT_HANDLER: case content::PermissionType::NUM: break; } - return BrowserContextAdapter::UnsupportedPermission; + return ProfileAdapter::UnsupportedPermission; } PermissionManagerQt::PermissionManagerQt() @@ -86,9 +88,9 @@ PermissionManagerQt::~PermissionManagerQt() { } -void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserContextAdapter::PermissionType type, bool reply) +void PermissionManagerQt::permissionRequestReply(const QUrl &origin, ProfileAdapter::PermissionType type, bool reply) { - QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, type); + QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type); m_permissions[key] = reply; blink::mojom::PermissionStatus status = reply ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED; { @@ -101,7 +103,7 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont ++it; } } - Q_FOREACH (const RequestOrSubscription &subscriber, m_subscribers) { + for (const RequestOrSubscription &subscriber : qAsConst(m_subscribers)) { if (subscriber.origin == origin && subscriber.type == type) subscriber.callback.Run(status); } @@ -113,13 +115,13 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont std::vector<blink::mojom::PermissionStatus> result; result.reserve(it->types.size()); for (content::PermissionType permission : it->types) { - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) { + const ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::UnsupportedPermission) { result.push_back(blink::mojom::PermissionStatus::DENIED); continue; } - QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, permissionType); + QPair<QUrl, ProfileAdapter::PermissionType> key(origin, permissionType); if (!m_permissions.contains(key)) { answerable = false; break; @@ -139,9 +141,9 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont } } -bool PermissionManagerQt::checkPermission(const QUrl &origin, BrowserContextAdapter::PermissionType type) +bool PermissionManagerQt::checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type) { - QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, type); + QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type); return m_permissions.contains(key) && m_permissions[key]; } @@ -152,14 +154,14 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { int request_id = ++m_requestIdCount; - BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) { + ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::UnsupportedPermission) { callback.Run(blink::mojom::PermissionStatus::DENIED); - return kNoPendingOperation; + return content::PermissionController::kNoPendingOperation; } // Audio and video-capture should not come this way currently - Q_ASSERT(permissionType != BrowserContextAdapter::AudioCapturePermission - && permissionType != BrowserContextAdapter::VideoCapturePermission); + Q_ASSERT(permissionType != ProfileAdapter::AudioCapturePermission + && permissionType != ProfileAdapter::VideoCapturePermission); content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents(); WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); @@ -170,7 +172,7 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission, callback }; m_requests.insert(request_id, request); - if (permissionType == BrowserContextAdapter::GeolocationPermission) + if (permissionType == ProfileAdapter::GeolocationPermission) contentsDelegate->requestGeolocationPermission(request.origin); return request_id; } @@ -185,8 +187,8 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio std::vector<blink::mojom::PermissionStatus> result; result.reserve(permissions.size()); for (content::PermissionType permission : permissions) { - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) + const ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::UnsupportedPermission) result.push_back(blink::mojom::PermissionStatus::DENIED); else { answerable = false; @@ -195,7 +197,7 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio } if (answerable) { callback.Run(result); - return kNoPendingOperation; + return content::PermissionController::kNoPendingOperation; } int request_id = ++m_requestIdCount; @@ -209,30 +211,23 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio }; m_multiRequests.insert(request_id, request); for (content::PermissionType permission : permissions) { - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::GeolocationPermission) + const ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::GeolocationPermission) contentsDelegate->requestGeolocationPermission(request.origin); } return request_id; } -void PermissionManagerQt::CancelPermissionRequest(int request_id) -{ - // Should we add API to cancel permissions in the UI level? - m_requests.remove(request_id); - m_multiRequests.remove(request_id); -} - blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( content::PermissionType permission, const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) + const ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::UnsupportedPermission) return blink::mojom::PermissionStatus::DENIED; - QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType); + QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType); if (!m_permissions.contains(key)) return blink::mojom::PermissionStatus::ASK; if (m_permissions[key]) @@ -240,16 +235,27 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus( return blink::mojom::PermissionStatus::DENIED; } +blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForFrame( + content::PermissionType permission, + content::RenderFrameHost *render_frame_host, + const GURL &requesting_origin) +{ + return GetPermissionStatus( + permission, + requesting_origin, + content::WebContents::FromRenderFrameHost(render_frame_host)->GetLastCommittedURL().GetOrigin()); +} + void PermissionManagerQt::ResetPermission( content::PermissionType permission, const GURL& requesting_origin, const GURL& /*embedding_origin*/) { - const BrowserContextAdapter::PermissionType permissionType = toQt(permission); - if (permissionType == BrowserContextAdapter::UnsupportedPermission) + const ProfileAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == ProfileAdapter::UnsupportedPermission) return; - QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType); + QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType); m_permissions.remove(key); } diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index c76b377f4..b3bd3dc7a 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -41,19 +41,20 @@ #define PERMISSION_MANAGER_QT_H #include "base/callback.h" -#include "content/public/browser/permission_manager.h" -#include "browser_context_adapter.h" +#include "content/public/browser/permission_controller_delegate.h" + +#include "profile_adapter.h" #include <QHash> namespace QtWebEngineCore { -class PermissionManagerQt : public content::PermissionManager { +class PermissionManagerQt : public content::PermissionControllerDelegate { public: PermissionManagerQt(); ~PermissionManagerQt(); - typedef BrowserContextAdapter::PermissionType PermissionType; + typedef ProfileAdapter::PermissionType PermissionType; void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); bool checkPermission(const QUrl &origin, PermissionType type); @@ -66,13 +67,16 @@ public: bool user_gesture, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; - void CancelPermissionRequest(int request_id) override; - blink::mojom::PermissionStatus GetPermissionStatus( content::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + blink::mojom::PermissionStatus GetPermissionStatusForFrame( + content::PermissionType permission, + content::RenderFrameHost *render_frame_host, + const GURL& requesting_origin) override; + void ResetPermission( content::PermissionType permission, const GURL& requesting_origin, diff --git a/src/core/printing/pdfium_document_wrapper_qt.cpp b/src/core/printing/pdfium_document_wrapper_qt.cpp index a7433b2cc..a18258d0e 100644 --- a/src/core/printing/pdfium_document_wrapper_qt.cpp +++ b/src/core/printing/pdfium_document_wrapper_qt.cpp @@ -36,11 +36,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "pdf/features.h" -#if BUILDFLAG(ENABLE_PDF) #include "pdfium_document_wrapper_qt.h" - #include <QtCore/qhash.h> #include <QtGui/qimage.h> #include <QtGui/qpainter.h> @@ -51,9 +48,9 @@ namespace QtWebEngineCore { int PdfiumDocumentWrapperQt::m_libraryUsers = 0; -class QWEBENGINE_EXPORT PdfiumPageWrapperQt { +class QWEBENGINECORE_PRIVATE_EXPORT PdfiumPageWrapperQt { public: - PdfiumPageWrapperQt(void *data, int pageIndex, int targetWidth, int targetHeight) + PdfiumPageWrapperQt(FPDF_DOCUMENT data, int pageIndex, int targetWidth, int targetHeight) : m_pageData(FPDF_LoadPage(data, pageIndex)) , m_width(FPDF_GetPageWidth(m_pageData)) , m_height(FPDF_GetPageHeight(m_pageData)) @@ -91,7 +88,7 @@ private: if (targetHeight <= 0) targetHeight = m_height; - QImage image(targetWidth, targetHeight, QImage::Format_RGBA8888); + QImage image(targetWidth, targetHeight, QImage::Format_ARGB32); Q_ASSERT(!image.isNull()); image.fill(0xFFFFFFFF); @@ -105,20 +102,11 @@ private: 0, 0); FPDFBitmap_Destroy(bitmap); bitmap = nullptr; - - // Map BGRA to RGBA as PDFium currently does not support RGBA bitmaps directly - for (int i = 0; i < image.height(); i++) { - uchar *pixels = image.scanLine(i); - for (int j = 0; j < image.width(); j++) { - qSwap(pixels[0], pixels[2]); - pixels += 4; - } - } - return image; + return std::move(image); } private: - void *m_pageData; + FPDF_PAGE m_pageData; int m_width; int m_height; int m_index; @@ -136,8 +124,8 @@ PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t siz if (m_libraryUsers++ == 0) FPDF_InitLibrary(); - m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); - m_pageCount = FPDF_GetPageCount(m_documentHandle); + m_documentHandle = (void *)FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password); + m_pageCount = FPDF_GetPageCount((FPDF_DOCUMENT)m_documentHandle); } QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) @@ -152,17 +140,16 @@ QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index) return QImage(); } - PdfiumPageWrapperQt pageWrapper(m_documentHandle, index, + PdfiumPageWrapperQt pageWrapper((FPDF_DOCUMENT)m_documentHandle, index, m_imageSize.width(), m_imageSize.height()); return pageWrapper.image(); } PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt() { - FPDF_CloseDocument(m_documentHandle); + FPDF_CloseDocument((FPDF_DOCUMENT)m_documentHandle); if (--m_libraryUsers == 0) FPDF_DestroyLibrary(); } } -#endif // BUILDFLAG(ENABLE_PDF) diff --git a/src/core/printing/pdfium_document_wrapper_qt.h b/src/core/printing/pdfium_document_wrapper_qt.h index 7886c51c0..f4ac557a0 100644 --- a/src/core/printing/pdfium_document_wrapper_qt.h +++ b/src/core/printing/pdfium_document_wrapper_qt.h @@ -37,17 +37,28 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef PDFIUM_DOCUMENT_WRAPPER_QT_H #define PDFIUM_DOCUMENT_WRAPPER_QT_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QtGui/qimage.h> namespace QtWebEngineCore { class PdfiumPageWrapperQt; -class QWEBENGINE_EXPORT PdfiumDocumentWrapperQt +class QWEBENGINECORE_PRIVATE_EXPORT PdfiumDocumentWrapperQt { public: PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index abc1edf74..0e7239ef8 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -72,15 +72,13 @@ namespace QtWebEngineCore { PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) - , cookie_(0) , m_isInsideInnerMessageLoop(false) -#if !defined(OS_MACOSX) - , m_isExpectingFirstPage(false) -#endif , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) + , m_printingRFH(nullptr) { // FIXME: Check if this needs to be executed async: + // TODO: Add isEnabled to profile PrintViewManagerBaseQt::UpdatePrintingEnabled(); } @@ -90,10 +88,17 @@ PrintViewManagerBaseQt::~PrintViewManagerBaseQt() DisconnectFromCurrentPrintJob(); } +void PrintViewManagerBaseQt::SetPrintingRFH(content::RenderFrameHost *rfh) +{ + DCHECK(!m_printingRFH); + m_printingRFH = rfh; +} + void PrintViewManagerBaseQt::UpdatePrintingEnabled() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); bool enabled = false; -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) enabled = true; #endif web_contents()->ForEachFrame( @@ -112,24 +117,19 @@ base::string16 PrintViewManagerBaseQt::RenderSourceName() return toString16(QLatin1String("")); } -bool PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedBytes> &print_data, +void PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document, + const scoped_refptr<base::RefCountedMemory> &print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets) { std::unique_ptr<printing::PdfMetafileSkia> metafile = - std::make_unique<printing::PdfMetafileSkia>(printing::SkiaDocumentType::PDF); - if (!metafile->InitFromData(print_data->front(), print_data->size())) { - NOTREACHED() << "Invalid metafile"; - web_contents()->Stop(); - return false; - } + std::make_unique<printing::PdfMetafileSkia>(); + CHECK(metafile->InitFromData(print_data->front(), print_data->size())); // Update the rendered document. It will send notifications to the listener. document->SetDocument(std::move(metafile), page_size, content_area); ShouldQuitFromInnerMessageLoop(); - return true; } printing::PrintedDocument *PrintViewManagerBaseQt::GetDocument(int cookie) @@ -147,29 +147,31 @@ printing::PrintedDocument *PrintViewManagerBaseQt::GetDocument(int cookie) } // IPC handlers -void PrintViewManagerBaseQt::OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params ¶ms) +void PrintViewManagerBaseQt::OnDidPrintDocument(content::RenderFrameHost* /*render_frame_host*/, + const PrintHostMsg_DidPrintDocument_Params ¶ms) { printing::PrintedDocument *document = GetDocument(params.document_cookie); if (!document) return; - if (!base::SharedMemory::IsHandleValid(params.metafile_data_handle)) { + const PrintHostMsg_DidPrintContent_Params &content = params.content; + if (!base::SharedMemory::IsHandleValid(content.metafile_data_handle)) { NOTREACHED() << "invalid memory handle"; web_contents()->Stop(); return; } std::unique_ptr<base::SharedMemory> shared_buf = - std::make_unique<base::SharedMemory>(params.metafile_data_handle, true); - if (!shared_buf->Map(params.data_size)) { + std::make_unique<base::SharedMemory>(content.metafile_data_handle, true); + if (!shared_buf->Map(content.data_size)) { NOTREACHED() << "couldn't map"; web_contents()->Stop(); return; } - scoped_refptr<base::RefCountedBytes> bytes = - base::MakeRefCounted<base::RefCountedBytes>( - reinterpret_cast<const unsigned char*>(shared_buf->memory()), params.data_size); - PrintDocument(document, bytes, params.page_size, params.content_area, params.physical_offsets); + auto data = base::MakeRefCounted<base::RefCountedSharedMemory>( + std::move(shared_buf), content.data_size); + PrintDocument(document, data, params.page_size, params.content_area, + params.physical_offsets); } void PrintViewManagerBaseQt::OnShowInvalidPrinterSettingsError() @@ -181,12 +183,16 @@ void PrintViewManagerBaseQt::DidStartLoading() UpdatePrintingEnabled(); } +// Note: In PrintViewManagerQt we always initiate printing with PrintMsg_InitiatePrintPreview +// so m_printingRFH is never set and used at the moment. void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) { // Terminates or cancels the print job if one was pending. - if (render_frame_host != web_contents()->GetMainFrame()) + if (render_frame_host != m_printingRFH) return; + m_printingRFH = nullptr; + PrintManager::PrintingRenderFrameDeleted(); ReleasePrinterQuery(); @@ -202,12 +208,20 @@ void PrintViewManagerBaseQt::RenderFrameDeleted(content::RenderFrameHost *render } } -bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) +bool PrintViewManagerBaseQt::OnMessageReceived(const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) + IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerBaseQt, message, render_frame_host) IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument) - IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, OnShowInvalidPrinterSettingsError); + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + if (handled) + return true; + handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBaseQt, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError, + OnShowInvalidPrinterSettingsError); IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled || PrintManager::OnMessageReceived(message, render_frame_host); @@ -224,7 +238,7 @@ void PrintViewManagerBaseQt::Observe(int type, void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details) { switch (event_details.type()) { - case printing::JobEventDetails::FAILED: + case printing::JobEventDetails::FAILED: { TerminatePrintJob(true); content::NotificationService::current()->Notify( @@ -232,21 +246,26 @@ void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetai content::Source<content::WebContents>(web_contents()), content::NotificationService::NoDetails()); break; + } case printing::JobEventDetails::USER_INIT_DONE: case printing::JobEventDetails::DEFAULT_INIT_DONE: - case printing::JobEventDetails::USER_INIT_CANCELED: + case printing::JobEventDetails::USER_INIT_CANCELED: { NOTREACHED(); break; - case printing::JobEventDetails::ALL_PAGES_REQUESTED: + } + case printing::JobEventDetails::ALL_PAGES_REQUESTED: { + ShouldQuitFromInnerMessageLoop(); break; + } case printing::JobEventDetails::NEW_DOC: #if defined(OS_WIN) case printing::JobEventDetails::PAGE_DONE: #endif - case printing::JobEventDetails::DOC_DONE: + case printing::JobEventDetails::DOC_DONE: { // Don't care about the actual printing process. break; - case printing::JobEventDetails::JOB_DONE: + } + case printing::JobEventDetails::JOB_DONE: { // Printing is done, we don't need it anymore. // print_job_->is_job_pending() may still be true, depending on the order // of object registration. @@ -258,6 +277,7 @@ void PrintViewManagerBaseQt::OnNotifyPrintJobEvent(const printing::JobEventDetai content::Source<content::WebContents>(web_contents()), content::NotificationService::NoDetails()); break; + } default: NOTREACHED(); break; @@ -272,6 +292,12 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() if (!m_printJob.get() || !m_printJob->is_job_pending()) return false; + // Is the document already complete? + if (m_printJob->document() && m_printJob->document()->IsComplete()) { + m_didPrintingSucceed = true; + return true; + } + // We can't print if there is no renderer. if (!web_contents() || !web_contents()->GetRenderViewHost() || @@ -279,12 +305,6 @@ bool PrintViewManagerBaseQt::RenderAllMissingPagesNow() return false; } - // Is the document already complete? - if (m_printJob->document() && m_printJob->document()->IsComplete()) { - m_didPrintingSucceed = true; - return true; - } - // WebContents is either dying or a second consecutive request to print // happened before the first had time to finish. We need to render all the // pages in an hurry if a print_job_ is still pending. No need to wait for it @@ -318,12 +338,12 @@ void PrintViewManagerBaseQt::ShouldQuitFromInnerMessageLoop() m_isInsideInnerMessageLoop) { // We are in a message loop created by RenderAllMissingPagesNow. Quit from // it. - base::MessageLoop::current()->QuitWhenIdleClosure(); + base::RunLoop::QuitCurrentWhenIdleDeprecated(); m_isInsideInnerMessageLoop = false; } } -bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrintJobWorkerOwner* job) +bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrinterQuery *job) { DCHECK(!m_isInsideInnerMessageLoop); @@ -343,7 +363,7 @@ bool PrintViewManagerBaseQt::CreateNewPrintJob(printing::PrintJobWorkerOwner* jo if (!job) return false; - m_printJob = new printing::PrintJob(); + m_printJob = base::MakeRefCounted<printing::PrintJob>(); m_printJob->Initialize(job, RenderSourceName(), number_pages_); m_registrar.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<printing::PrintJob>(m_printJob.get())); @@ -368,9 +388,6 @@ void PrintViewManagerBaseQt::DisconnectFromCurrentPrintJob() // DO NOT wait for the job to finish. ReleasePrintJob(); } -#if !defined(OS_MACOSX) - m_isExpectingFirstPage = true; -#endif } void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) @@ -396,13 +413,18 @@ void PrintViewManagerBaseQt::TerminatePrintJob(bool cancel) void PrintViewManagerBaseQt::ReleasePrintJob() { - content::RenderFrameHost *rfh = web_contents() ? web_contents()->GetMainFrame() : nullptr; + content::RenderFrameHost* rfh = m_printingRFH; + m_printingRFH = nullptr; if (!m_printJob.get()) return; - if (rfh) - rfh->Send(new PrintMsg_PrintingDone(rfh->GetRoutingID(), m_didPrintingSucceed)); + if (rfh) { + auto msg = std::make_unique<PrintMsg_PrintingDone>(rfh->GetRoutingID(), + m_didPrintingSucceed); + rfh->Send(msg.release()); + } + m_registrar.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<printing::PrintJob>(m_printJob.get())); @@ -410,7 +432,6 @@ void PrintViewManagerBaseQt::ReleasePrintJob() m_printJob = nullptr; } - bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // This value may actually be too low: // @@ -425,19 +446,17 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop() { // memory-bound. static const int kPrinterSettingsTimeout = 60000; base::OneShotTimer quit_timer; - base::RunLoop runLoop; + base::RunLoop run_loop; quit_timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), - runLoop.QuitWhenIdleClosure()); + run_loop.QuitWhenIdleClosure()); m_isInsideInnerMessageLoop = true; // Need to enable recursive task. { - m_quitClosure = runLoop.QuitClosure(); - base::MessageLoop* loop = base::MessageLoop::current(); - base::MessageLoop::ScopedNestableTaskAllower allowNested(loop); - runLoop.Run(); + base::MessageLoop::ScopedNestableTaskAllower allow; + run_loop.Run(); } bool success = true; diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h index 0d86fcf90..3ade02f0d 100644 --- a/src/core/printing/print_view_manager_base_qt.h +++ b/src/core/printing/print_view_manager_base_qt.h @@ -44,7 +44,7 @@ #ifndef PRINT_VIEW_MANAGER_BASE_QT_H #define PRINT_VIEW_MANAGER_BASE_QT_H -#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" #include "base/strings/string16.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" @@ -87,6 +87,8 @@ public: protected: explicit PrintViewManagerBaseQt(content::WebContents*); + void SetPrintingRFH(content::RenderFrameHost* rfh); + // content::WebContentsObserver implementation. // Cancels the print job. void NavigationStopped() override; @@ -97,16 +99,13 @@ protected: content::RenderFrameHost* render_frame_host) override; // IPC Message handlers. - void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params); + void OnDidPrintDocument(content::RenderFrameHost* render_frame_host, + const PrintHostMsg_DidPrintDocument_Params& params); void OnShowInvalidPrinterSettingsError(); // Processes a NOTIFY_PRINT_JOB_EVENT notification. void OnNotifyPrintJobEvent(const printing::JobEventDetails& event_details); - int number_pages_; // Number of pages to print in the print job. - int cookie_; - std::unique_ptr<base::DictionaryValue> m_printSettings; - // content::NotificationObserver implementation. void Observe(int, const content::NotificationSource&, @@ -130,8 +129,8 @@ protected: // Starts printing a document with data given in |print_data|. |print_data| // must successfully initialize a metafile. |document| is the printed // document associated with the print job. Returns true if successful. - bool PrintDocument(printing::PrintedDocument *document, - const scoped_refptr<base::RefCountedBytes> &print_data, + void PrintDocument(printing::PrintedDocument *document, + const scoped_refptr<base::RefCountedMemory> &print_data, const gfx::Size &page_size, const gfx::Rect &content_area, const gfx::Point &offsets); @@ -148,28 +147,24 @@ protected: void TerminatePrintJob(bool cancel); void DisconnectFromCurrentPrintJob(); - bool CreateNewPrintJob(printing::PrintJobWorkerOwner* job); + bool CreateNewPrintJob(printing::PrinterQuery *job); void ReleasePrintJob(); void ReleasePrinterQuery(); private: // Helper method for UpdatePrintingEnabled(). void SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh); + // content::WebContentsObserver implementation. + void DidStartLoading() override; +private: content::NotificationRegistrar m_registrar; scoped_refptr<printing::PrintJob> m_printJob; - // Closure for quitting nested message loop. - base::Closure m_quitClosure; - bool m_isInsideInnerMessageLoop; -#if !defined(OS_MACOSX) - bool m_isExpectingFirstPage; -#endif bool m_didPrintingSucceed; scoped_refptr<printing::PrintQueriesQueue> m_printerQueriesQueue; - // content::WebContentsObserver implementation. - void DidStartLoading() override; - + // The current RFH that is printing with a system printing dialog. + content::RenderFrameHost* m_printingRFH; DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBaseQt); }; diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index 627afb01a..ff9fc76be 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -44,6 +44,8 @@ #include "print_view_manager_qt.h" #include "type_conversion.h" +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" #include "web_engine_context.h" #include <QtGui/qpagelayout.h> @@ -51,10 +53,12 @@ #include "base/values.h" #include "base/memory/ref_counted_memory.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printer_query.h" #include "components/printing/common/print_messages.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/common/web_preferences.h" @@ -65,6 +69,7 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt); namespace { + static const qreal kMicronsToMillimeter = 1000.0f; static std::vector<char> @@ -84,11 +89,10 @@ GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) static scoped_refptr<base::RefCountedBytes> GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) { - std::unique_ptr<base::SharedMemory> shared_buf( - new base::SharedMemory(handle, true)); + std::unique_ptr<base::SharedMemory> shared_buf(new base::SharedMemory(handle, true)); if (!shared_buf->Map(data_size)) { - return NULL; + return nullptr; } unsigned char* data = static_cast<unsigned char*>(shared_buf->memory()); @@ -98,14 +102,13 @@ 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 QtWebEngineCore::PrintViewManagerQt::PrintToPDFFileCallback - &saveCallback) + const base::FilePath &path, + const QtWebEngineCore::PrintViewManagerQt::PrintToPDFFileCallback &saveCallback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); + base::AssertBlockingAllowed(); DCHECK_GT(data->size(), 0U); - printing::PdfMetafileSkia metafile(printing::SkiaDocumentType::PDF); + printing::PdfMetafileSkia metafile; metafile.InitFromData(static_cast<const void*>(data->front()), data->size()); base::File file(path, @@ -131,16 +134,13 @@ static base::DictionaryValue *createPrintSettings() printSettings->SetBoolean(printing::kSettingPrintWithPrivet, false); printSettings->SetBoolean(printing::kSettingPrintWithExtension, false); - printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); - printSettings->SetBoolean(printing::kSettingPreviewModifiable, false); - printSettings->SetInteger(printing::kSettingDpiHorizontal, printing::kPointsPerInch); printSettings->SetInteger(printing::kSettingDpiVertical, printing::kPointsPerInch); printSettings->SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX); printSettings->SetInteger(printing::kSettingCopies, 1); printSettings->SetBoolean(printing::kSettingCollate, false); - printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); +// printSettings->SetBoolean(printing::kSettingGenerateDraftData, false); printSettings->SetBoolean(printing::kSettingPreviewModifiable, false); printSettings->SetBoolean(printing::kSettingShouldPrintSelectionOnly, false); @@ -196,11 +196,23 @@ static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayo namespace QtWebEngineCore { +struct PrintViewManagerQt::FrameDispatchHelper { + PrintViewManagerQt* m_manager; + content::RenderFrameHost* m_renderFrameHost; + + bool Send(IPC::Message* msg) { + return m_renderFrameHost->Send(msg); + } + + void OnSetupScriptedPrintPreview(IPC::Message* reply_msg) { + m_manager->OnSetupScriptedPrintPreview(m_renderFrameHost, reply_msg); + } +}; + PrintViewManagerQt::~PrintViewManagerQt() { } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayout, bool printInColor, const QString &filePath, @@ -210,8 +222,7 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou return; if (m_printSettings || !filePath.length()) { - content::BrowserThread::PostTask(content::BrowserThread::UI, - FROM_HERE, + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false)); return; } @@ -219,8 +230,7 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou m_pdfOutputPath = toFilePath(filePath); m_pdfSaveCallback = callback; if (!PrintToPDFInternal(pageLayout, printInColor)) { - content::BrowserThread::PostTask(content::BrowserThread::UI, - FROM_HERE, + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false)); resetPdfState(); } @@ -236,9 +246,8 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, // 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>())); + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(callback, std::vector<char>())); return; } @@ -260,39 +269,68 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, return false; m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout, useCustomMargins)); - m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds - , web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds); + m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, + web_contents()->GetRenderViewHost()-> + GetWebkitPreferences().should_print_backgrounds); m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE); - return web_contents()->GetMainFrame()->Send( - new PrintMsg_InitiatePrintPreview(web_contents()->GetMainFrame()->GetRoutingID(), false)); -} -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) + if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed()) + return false; + + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + auto message = std::make_unique<PrintMsg_InitiatePrintPreview>( + rfh->GetRoutingID(), false); + + DCHECK(!m_printPreviewRfh); + + if (!rfh->Send(message.release())) { + return false; + } + + m_printPreviewRfh = rfh; + return true; +} // PrintedPagesSource implementation. base::string16 PrintViewManagerQt::RenderSourceName() { - return toString16(QLatin1String("")); + return base::string16(); } PrintViewManagerQt::PrintViewManagerQt(content::WebContents *contents) : PrintViewManagerBaseQt(contents) + , m_printPreviewRfh(nullptr) { } // content::WebContentsObserver implementation. -bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) +bool PrintViewManagerQt::OnMessageReceived(const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { + FrameDispatchHelper helper = {this, render_frame_host}; bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintViewManagerQt, message) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) - IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview, OnRequestPrintPreview) - IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting, OnMetafileReadyForPrinting); - IPC_MESSAGE_UNHANDLED(handled = false) + IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerQt, message, render_frame_host); + IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) + IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview, OnRequestPrintPreview) + IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting, OnMetafileReadyForPrinting); + IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage) + IPC_MESSAGE_FORWARD_DELAY_REPLY( + PrintHostMsg_SetupScriptedPrintPreview, &helper, + FrameDispatchHelper::OnSetupScriptedPrintPreview) + IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview, + OnShowScriptedPrintPreview) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() - return handled || PrintManager::OnMessageReceived(message, render_frame_host); + return handled || PrintViewManagerBaseQt::OnMessageReceived(message, render_frame_host); +} + +void PrintViewManagerQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host) +{ + if (render_frame_host == m_printPreviewRfh) + PrintPreviewDone(); + PrintViewManagerBaseQt::RenderFrameDeleted(render_frame_host); } void PrintViewManagerQt::resetPdfState() @@ -308,13 +346,14 @@ void PrintViewManagerQt::resetPdfState() void PrintViewManagerQt::OnRequestPrintPreview( const PrintHostMsg_RequestPrintPreview_Params &/*params*/) { - auto *rfh = web_contents()->GetMainFrame(); - rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), *m_printSettings)); - rfh->Send(new PrintMsg_ClosePrintPreviewDialog(rfh->GetRoutingID())); + m_printPreviewRfh->Send(new PrintMsg_PrintPreview(m_printPreviewRfh->GetRoutingID(), + *m_printSettings)); + PrintPreviewDone(); } -void PrintViewManagerQt::OnMetafileReadyForPrinting( - const PrintHostMsg_DidPreviewDocument_Params& params) +void PrintViewManagerQt::OnMetafileReadyForPrinting(content::RenderFrameHost* rfh, + const PrintHostMsg_DidPreviewDocument_Params& params, + const PrintHostMsg_PreviewIds &ids) { StopWorker(params.document_cookie); @@ -326,17 +365,16 @@ void PrintViewManagerQt::OnMetafileReadyForPrinting( 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.content.metafile_data_handle, + params.content.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); - content::BrowserThread::PostTask(content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback)); + = GetBytesFromHandle(params.content.metafile_data_handle, params.content.data_size); + base::PostTaskWithTraits(FROM_HERE, {base::MayBlock()}, + base::BindOnce(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback)); } } @@ -359,6 +397,7 @@ void PrintViewManagerQt::NavigationStopped() base::Bind(m_pdfPrintCallback, std::vector<char>())); } resetPdfState(); + PrintViewManagerBaseQt::NavigationStopped(); } void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) @@ -372,5 +411,41 @@ void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status) resetPdfState(); } +void PrintViewManagerQt::OnDidPreviewPage(content::RenderFrameHost* rfh, + const PrintHostMsg_DidPreviewPage_Params& params, + const PrintHostMsg_PreviewIds& ids) +{ + // just consume the message, this is just for sending 'page-preview-ready' for webui +} + +void PrintViewManagerQt::OnSetupScriptedPrintPreview(content::RenderFrameHost* rfh, + IPC::Message* reply_msg) +{ + // ignore the scripted print + rfh->Send(reply_msg); + + content::WebContentsView *view = static_cast<content::WebContentsImpl*>(web_contents())->GetView(); + WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client(); + + if (!client) + return; + + // close preview + rfh->Send(new PrintMsg_ClosePrintPreviewDialog(rfh->GetRoutingID())); + + client->printRequested(); +} + +void PrintViewManagerQt::OnShowScriptedPrintPreview(content::RenderFrameHost* rfh, + bool source_is_modifiable) +{ + // ignore for now +} + +void PrintViewManagerQt::PrintPreviewDone() { + m_printPreviewRfh->Send(new PrintMsg_ClosePrintPreviewDialog( + m_printPreviewRfh->GetRoutingID())); + m_printPreviewRfh = nullptr; +} } // namespace QtWebEngineCore diff --git a/src/core/printing/print_view_manager_qt.h b/src/core/printing/print_view_manager_qt.h index 654608ddd..209be8782 100644 --- a/src/core/printing/print_view_manager_qt.h +++ b/src/core/printing/print_view_manager_qt.h @@ -46,15 +46,15 @@ #include "print_view_manager_base_qt.h" -#include <QtWebEngineCore/qtwebenginecoreglobal.h> +#include "qtwebenginecoreglobal_p.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" +#include "components/printing/common/print_messages.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_user_data.h" -#include "printing/features/features.h" struct PrintHostMsg_RequestPrintPreview_Params; struct PrintHostMsg_DidPreviewDocument_Params; @@ -78,14 +78,14 @@ QT_END_NAMESPACE namespace QtWebEngineCore { class PrintViewManagerQt - : PrintViewManagerBaseQt + : public PrintViewManagerBaseQt , public content::WebContentsUserData<PrintViewManagerQt> { public: ~PrintViewManagerQt() override; typedef base::Callback<void(const std::vector<char> &result)> PrintToPDFCallback; typedef base::Callback<void(bool success)> PrintToPDFFileCallback; -#if BUILDFLAG(ENABLE_BASIC_PRINTING) + // Method to print a page to a Pdf document with page size \a pageSize in location \a filePath. void PrintToPDFFileWithCallback(const QPageLayout &pageLayout, bool printInColor, @@ -95,7 +95,6 @@ public: bool printInColor, bool useCustomMargins, const PrintToPDFCallback &callback); -#endif // ENABLE_BASIC_PRINTING base::string16 RenderSourceName() override; @@ -112,28 +111,38 @@ protected: // content::WebContentsObserver implementation. bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; // IPC handlers void OnDidShowPrintDialog(); void OnRequestPrintPreview(const PrintHostMsg_RequestPrintPreview_Params&); - void OnMetafileReadyForPrinting(const PrintHostMsg_DidPreviewDocument_Params& params); - -#if BUILDFLAG(ENABLE_BASIC_PRINTING) + void OnMetafileReadyForPrinting(content::RenderFrameHost* rfh, + const PrintHostMsg_DidPreviewDocument_Params& params, + const PrintHostMsg_PreviewIds &ids); + void OnSetupScriptedPrintPreview(content::RenderFrameHost* rfh, + IPC::Message* reply_msg); + void OnDidPreviewPage(content::RenderFrameHost* rfh, + const PrintHostMsg_DidPreviewPage_Params& params, + const PrintHostMsg_PreviewIds& ids); + void OnShowScriptedPrintPreview(content::RenderFrameHost* rfh, + bool source_is_modifiable); bool PrintToPDFInternal(const QPageLayout &, bool printInColor, bool useCustomMargins = true); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) - - base::FilePath m_pdfOutputPath; - PrintToPDFCallback m_pdfPrintCallback; - PrintToPDFFileCallback m_pdfSaveCallback; private: - friend class content::WebContentsUserData<PrintViewManagerQt>; - void resetPdfState(); - // content::WebContentsObserver implementation. void DidStartLoading() override; + void PrintPreviewDone(); + +private: + content::RenderFrameHost *m_printPreviewRfh; + base::FilePath m_pdfOutputPath; + PrintToPDFCallback m_pdfPrintCallback; + PrintToPDFFileCallback m_pdfSaveCallback; + std::unique_ptr<base::DictionaryValue> m_printSettings; + friend class content::WebContentsUserData<PrintViewManagerQt>; DISALLOW_COPY_AND_ASSIGN(PrintViewManagerQt); + struct FrameDispatchHelper; }; } // namespace QtWebEngineCore diff --git a/src/core/printing/printing_message_filter_qt.cpp b/src/core/printing/printing_message_filter_qt.cpp index c0e3498ee..db59a0807 100644 --- a/src/core/printing/printing_message_filter_qt.cpp +++ b/src/core/printing/printing_message_filter_qt.cpp @@ -176,7 +176,7 @@ void PrintingMessageFilterQt::OnScriptedPrintReply( } PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); Send(reply_msg); - if (params.params.dpi && params.params.document_cookie) { + if (!params.params.dpi.IsEmpty() && params.params.document_cookie) { queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); @@ -229,9 +229,8 @@ void PrintingMessageFilterQt::OnUpdatePrintSettingsReply( } } -void PrintingMessageFilterQt::OnCheckForCancel(int32_t preview_ui_id, - int preview_request_id, - bool* cancel) { +void PrintingMessageFilterQt::OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, + bool* cancel) { *cancel = false; } diff --git a/src/core/printing/printing_message_filter_qt.h b/src/core/printing/printing_message_filter_qt.h index ca5e29f08..72e4b43b4 100644 --- a/src/core/printing/printing_message_filter_qt.h +++ b/src/core/printing/printing_message_filter_qt.h @@ -54,6 +54,7 @@ #include "base/memory/shared_memory.h" #endif +struct PrintHostMsg_PreviewIds; struct PrintHostMsg_ScriptedPrint_Params; namespace base { @@ -66,7 +67,6 @@ class WebContents; } namespace printing { - class PrintJobManager; class PrintQueriesQueue; class PrinterQuery; @@ -116,9 +116,7 @@ class PrintingMessageFilterQt : public content::BrowserMessageFilter { IPC::Message* reply_msg); // Check to see if print preview has been cancelled. - void OnCheckForCancel(int32_t preview_ui_id, - int preview_request_id, - bool* cancel); + void OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, bool* cancel); const int render_process_id_; diff --git a/src/core/process_main.h b/src/core/process_main.h index 890bf5a85..d171828d5 100644 --- a/src/core/process_main.h +++ b/src/core/process_main.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ -#include "qtwebenginecoreglobal.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 <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> namespace QtWebEngine { -QWEBENGINE_EXPORT int processMain(int argc, const char **argv); +QWEBENGINECORE_PRIVATE_EXPORT int processMain(int argc, const char **argv); } // namespace diff --git a/src/core/browser_context_adapter.cpp b/src/core/profile_adapter.cpp index b0f244393..86b16fd2c 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -37,25 +37,23 @@ ** ****************************************************************************/ -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/download_manager.h" -#include "browser_context_qt.h" #include "content_client_qt.h" #include "download_manager_delegate_qt.h" #include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" +#include "profile_qt.h" #include "renderer_host/user_resource_controller_host.h" #include "type_conversion.h" #include "visited_links_manager_qt.h" #include "web_engine_context.h" -#include "net/proxy/proxy_service.h" - #include "components/keyed_service/content/browser_context_dependency_manager.h" #include <QCoreApplication> @@ -76,162 +74,136 @@ inline QString buildLocationFromStandardPath(const QString &standardPath, const namespace QtWebEngineCore { -BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord) - : m_offTheRecord(offTheRecord) - , m_browserContext(new BrowserContextQt(this)) - , m_httpCacheType(DiskHttpCache) - , m_persistentCookiesPolicy(AllowPersistentCookies) - , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) - , m_httpCacheMaxSize(0) -{ - WebEngineContext::current(); // Ensure the WebEngineContext has been initialized - - // Mark the context as live. This prevents the use-after-free DCHECK in - // AssertBrowserContextWasntDestroyed from being triggered when a new - // BrowserContextQt object is allocated at the same address as a previously - // destroyed one. Needs to be called after WebEngineContext initialization. - BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(m_browserContext.data()); - - content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath())); -} - -BrowserContextAdapter::BrowserContextAdapter(const QString &storageName) - : m_name(storageName) - , m_offTheRecord(false) - , m_browserContext(new BrowserContextQt(this)) +ProfileAdapter::ProfileAdapter(const QString &storageName): + m_name(storageName) + , m_offTheRecord(storageName.isEmpty()) , m_httpCacheType(DiskHttpCache) , m_persistentCookiesPolicy(AllowPersistentCookies) , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) , m_httpCacheMaxSize(0) { - WebEngineContext::current(); // Ensure the WebEngineContext has been initialized - - // Mark the context as live. This prevents the use-after-free DCHECK in - // AssertBrowserContextWasntDestroyed from being triggered when a new - // BrowserContextQt object is allocated at the same address as a previously - // destroyed one. Needs to be called after WebEngineContext initialization. - BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(m_browserContext.data()); - - content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath())); + WebEngineContext::current()->addBrowserContext(this); + // creation of profile requires webengine context + m_profile.reset(new ProfileQt(this)); + content::BrowserContext::Initialize(m_profile.data(), toFilePath(dataPath())); + // fixme: this should not be here + m_profile->m_profileIOData->initializeOnUIThread(); } -BrowserContextAdapter::~BrowserContextAdapter() -{ - Q_ASSERT(!m_downloadManagerDelegate); - m_browserContext->ShutdownStoragePartitions(); -} - -void BrowserContextAdapter::shutdown() +ProfileAdapter::~ProfileAdapter() { + WebEngineContext::current()->removeBrowserContext(this); if (m_downloadManagerDelegate) { - m_browserContext->GetDownloadManager(m_browserContext.data())->Shutdown(); + m_profile->GetDownloadManager(m_profile.data())->Shutdown(); m_downloadManagerDelegate.reset(); } - BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data()); } -void BrowserContextAdapter::setStorageName(const QString &storageName) +void ProfileAdapter::setStorageName(const QString &storageName) { if (storageName == m_name) return; m_name = storageName; if (!m_offTheRecord) { - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateStorageSettings(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateStorageSettings(); if (m_visitedLinksManager) resetVisitedLinksManager(); } } -void BrowserContextAdapter::setOffTheRecord(bool offTheRecord) +void ProfileAdapter::setOffTheRecord(bool offTheRecord) { if (offTheRecord == m_offTheRecord) return; m_offTheRecord = offTheRecord; - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateStorageSettings(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateStorageSettings(); if (m_visitedLinksManager) resetVisitedLinksManager(); } -BrowserContextQt *BrowserContextAdapter::browserContext() +ProfileQt *ProfileAdapter::profile() { - return m_browserContext.data(); + return m_profile.data(); } -VisitedLinksManagerQt *BrowserContextAdapter::visitedLinksManager() +VisitedLinksManagerQt *ProfileAdapter::visitedLinksManager() { if (!m_visitedLinksManager) resetVisitedLinksManager(); return m_visitedLinksManager.data(); } -DownloadManagerDelegateQt *BrowserContextAdapter::downloadManagerDelegate() +DownloadManagerDelegateQt *ProfileAdapter::downloadManagerDelegate() { if (!m_downloadManagerDelegate) m_downloadManagerDelegate.reset(new DownloadManagerDelegateQt(this)); return m_downloadManagerDelegate.data(); } -QWebEngineCookieStore *BrowserContextAdapter::cookieStore() +QWebEngineCookieStore *ProfileAdapter::cookieStore() { if (!m_cookieStore) m_cookieStore.reset(new QWebEngineCookieStore); return m_cookieStore.data(); } -QWebEngineUrlRequestInterceptor *BrowserContextAdapter::requestInterceptor() +QWebEngineUrlRequestInterceptor *ProfileAdapter::requestInterceptor() { return m_requestInterceptor.data(); } -void BrowserContextAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +void ProfileAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) { if (m_requestInterceptor == interceptor) return; m_requestInterceptor = interceptor; - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateRequestInterceptor(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateRequestInterceptor(); } -void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient) +void ProfileAdapter::addClient(ProfileAdapterClient *adapterClient) { m_clients.append(adapterClient); } -void BrowserContextAdapter::removeClient(BrowserContextAdapterClient *adapterClient) +void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient) { m_clients.removeOne(adapterClient); - if (m_clients.isEmpty() && this != WebEngineContext::current()->m_defaultBrowserContext.data()) - shutdown(); } -void BrowserContextAdapter::cancelDownload(quint32 downloadId) +void ProfileAdapter::cancelDownload(quint32 downloadId) { downloadManagerDelegate()->cancelDownload(downloadId); } -void BrowserContextAdapter::pauseDownload(quint32 downloadId) +void ProfileAdapter::pauseDownload(quint32 downloadId) { downloadManagerDelegate()->pauseDownload(downloadId); } -void BrowserContextAdapter::resumeDownload(quint32 downloadId) +void ProfileAdapter::resumeDownload(quint32 downloadId) { downloadManagerDelegate()->resumeDownload(downloadId); } -QSharedPointer<BrowserContextAdapter> BrowserContextAdapter::defaultContext() +ProfileAdapter *ProfileAdapter::createDefaultProfileAdapter() +{ + return WebEngineContext::current()->createDefaultProfileAdapter(); +} + +ProfileAdapter *ProfileAdapter::defaultProfileAdapter() { - return WebEngineContext::current()->defaultBrowserContext(); + return WebEngineContext::current()->defaultProfileAdapter(); } -QObject* BrowserContextAdapter::globalQObjectRoot() +QObject* ProfileAdapter::globalQObjectRoot() { return WebEngineContext::current()->globalQObject(); } -QString BrowserContextAdapter::dataPath() const +QString ProfileAdapter::dataPath() const { if (m_offTheRecord) return QString(); @@ -242,20 +214,20 @@ QString BrowserContextAdapter::dataPath() const return QString(); } -void BrowserContextAdapter::setDataPath(const QString &path) +void ProfileAdapter::setDataPath(const QString &path) { if (m_dataPath == path) return; m_dataPath = path; if (!m_offTheRecord) { - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateStorageSettings(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateStorageSettings(); if (m_visitedLinksManager) resetVisitedLinksManager(); } } -QString BrowserContextAdapter::cachePath() const +QString ProfileAdapter::cachePath() const { if (m_offTheRecord) return QString(); @@ -266,16 +238,16 @@ QString BrowserContextAdapter::cachePath() const return QString(); } -void BrowserContextAdapter::setCachePath(const QString &path) +void ProfileAdapter::setCachePath(const QString &path) { if (m_cachePath == path) return; m_cachePath = path; - if (!m_offTheRecord && m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateHttpCache(); + if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateHttpCache(); } -QString BrowserContextAdapter::cookiesPath() const +QString ProfileAdapter::cookiesPath() const { if (m_offTheRecord) return QString(); @@ -290,7 +262,7 @@ QString BrowserContextAdapter::cookiesPath() const return QString(); } -QString BrowserContextAdapter::channelIdPath() const +QString ProfileAdapter::channelIdPath() const { if (m_offTheRecord) return QString(); @@ -300,7 +272,7 @@ QString BrowserContextAdapter::channelIdPath() const return QString(); } -QString BrowserContextAdapter::httpCachePath() const +QString ProfileAdapter::httpCachePath() const { if (m_offTheRecord) return QString(); @@ -310,29 +282,29 @@ QString BrowserContextAdapter::httpCachePath() const return QString(); } -QString BrowserContextAdapter::httpUserAgent() const +QString ProfileAdapter::httpUserAgent() const { if (m_httpUserAgent.isNull()) return QString::fromStdString(ContentClientQt::getUserAgent()); return m_httpUserAgent; } -void BrowserContextAdapter::setHttpUserAgent(const QString &userAgent) +void ProfileAdapter::setHttpUserAgent(const QString &userAgent) { if (m_httpUserAgent == userAgent) return; m_httpUserAgent = userAgent.simplified(); std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); - Q_FOREACH (content::WebContentsImpl *web_contents, list) - if (web_contents->GetBrowserContext() == m_browserContext.data()) - web_contents->SetUserAgentOverride(m_httpUserAgent.toStdString()); + for (content::WebContentsImpl *web_contents : list) + if (web_contents->GetBrowserContext() == m_profile.data()) + web_contents->SetUserAgentOverride(m_httpUserAgent.toStdString(), true); - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateUserAgent(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateUserAgent(); } -BrowserContextAdapter::HttpCacheType BrowserContextAdapter::httpCacheType() const +ProfileAdapter::HttpCacheType ProfileAdapter::httpCacheType() const { if (m_httpCacheType == NoCache) return NoCache; @@ -341,34 +313,34 @@ BrowserContextAdapter::HttpCacheType BrowserContextAdapter::httpCacheType() cons return m_httpCacheType; } -void BrowserContextAdapter::setHttpCacheType(BrowserContextAdapter::HttpCacheType newhttpCacheType) +void ProfileAdapter::setHttpCacheType(ProfileAdapter::HttpCacheType newhttpCacheType) { - BrowserContextAdapter::HttpCacheType oldCacheType = httpCacheType(); + ProfileAdapter::HttpCacheType oldCacheType = httpCacheType(); m_httpCacheType = newhttpCacheType; if (oldCacheType == httpCacheType()) return; - if (!m_offTheRecord && m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateHttpCache(); + if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateHttpCache(); } -BrowserContextAdapter::PersistentCookiesPolicy BrowserContextAdapter::persistentCookiesPolicy() const +ProfileAdapter::PersistentCookiesPolicy ProfileAdapter::persistentCookiesPolicy() const { if (isOffTheRecord() || cookiesPath().isEmpty()) return NoPersistentCookies; return m_persistentCookiesPolicy; } -void BrowserContextAdapter::setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy newPersistentCookiesPolicy) +void ProfileAdapter::setPersistentCookiesPolicy(ProfileAdapter::PersistentCookiesPolicy newPersistentCookiesPolicy) { - BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = persistentCookiesPolicy(); + ProfileAdapter::PersistentCookiesPolicy oldPolicy = persistentCookiesPolicy(); m_persistentCookiesPolicy = newPersistentCookiesPolicy; if (oldPolicy == persistentCookiesPolicy()) return; - if (!m_offTheRecord && m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateCookieStore(); + if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateCookieStore(); } -BrowserContextAdapter::VisitedLinksPolicy BrowserContextAdapter::visitedLinksPolicy() const +ProfileAdapter::VisitedLinksPolicy ProfileAdapter::visitedLinksPolicy() const { if (isOffTheRecord() || m_visitedLinksPolicy == DoNotTrackVisitedLinks) return DoNotTrackVisitedLinks; @@ -377,7 +349,7 @@ BrowserContextAdapter::VisitedLinksPolicy BrowserContextAdapter::visitedLinksPol return m_visitedLinksPolicy; } -bool BrowserContextAdapter::trackVisitedLinks() const +bool ProfileAdapter::trackVisitedLinks() const { switch (visitedLinksPolicy()) { case DoNotTrackVisitedLinks: @@ -388,7 +360,7 @@ bool BrowserContextAdapter::trackVisitedLinks() const return true; } -bool BrowserContextAdapter::persistVisitedLinks() const +bool ProfileAdapter::persistVisitedLinks() const { switch (visitedLinksPolicy()) { case DoNotTrackVisitedLinks: @@ -400,7 +372,7 @@ bool BrowserContextAdapter::persistVisitedLinks() const return true; } -void BrowserContextAdapter::setVisitedLinksPolicy(BrowserContextAdapter::VisitedLinksPolicy visitedLinksPolicy) +void ProfileAdapter::setVisitedLinksPolicy(ProfileAdapter::VisitedLinksPolicy visitedLinksPolicy) { if (m_visitedLinksPolicy == visitedLinksPolicy) return; @@ -409,37 +381,37 @@ void BrowserContextAdapter::setVisitedLinksPolicy(BrowserContextAdapter::Visited resetVisitedLinksManager(); } -int BrowserContextAdapter::httpCacheMaxSize() const +int ProfileAdapter::httpCacheMaxSize() const { return m_httpCacheMaxSize; } -void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize) +void ProfileAdapter::setHttpCacheMaxSize(int maxSize) { if (m_httpCacheMaxSize == maxSize) return; m_httpCacheMaxSize = maxSize; - if (!m_offTheRecord && m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateHttpCache(); + if (!m_offTheRecord && m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateHttpCache(); } -const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &BrowserContextAdapter::customUrlSchemeHandlers() const +const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &ProfileAdapter::customUrlSchemeHandlers() const { return m_customUrlSchemeHandlers; } -const QList<QByteArray> BrowserContextAdapter::customUrlSchemes() const +const QList<QByteArray> ProfileAdapter::customUrlSchemes() const { return m_customUrlSchemeHandlers.keys(); } -void BrowserContextAdapter::updateCustomUrlSchemeHandlers() +void ProfileAdapter::updateCustomUrlSchemeHandlers() { - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateJobFactory(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateJobFactory(); } -bool BrowserContextAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) +bool ProfileAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) { bool removedOneOrMore = false; auto it = m_customUrlSchemeHandlers.begin(); @@ -456,7 +428,7 @@ bool BrowserContextAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHand return removedOneOrMore; } -QWebEngineUrlSchemeHandler *BrowserContextAdapter::takeCustomUrlSchemeHandler(const QByteArray &scheme) +QWebEngineUrlSchemeHandler *ProfileAdapter::takeCustomUrlSchemeHandler(const QByteArray &scheme) { QWebEngineUrlSchemeHandler *handler = m_customUrlSchemeHandlers.take(scheme); if (handler) @@ -464,40 +436,40 @@ QWebEngineUrlSchemeHandler *BrowserContextAdapter::takeCustomUrlSchemeHandler(co return handler; } -void BrowserContextAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) +void ProfileAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) { m_customUrlSchemeHandlers.insert(scheme, handler); updateCustomUrlSchemeHandlers(); } -void BrowserContextAdapter::clearCustomUrlSchemeHandlers() +void ProfileAdapter::clearCustomUrlSchemeHandlers() { m_customUrlSchemeHandlers.clear(); updateCustomUrlSchemeHandlers(); } -UserResourceControllerHost *BrowserContextAdapter::userResourceController() +UserResourceControllerHost *ProfileAdapter::userResourceController() { if (!m_userResourceController) m_userResourceController.reset(new UserResourceControllerHost); return m_userResourceController.data(); } -void BrowserContextAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, bool reply) +void ProfileAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, bool reply) { - static_cast<PermissionManagerQt*>(browserContext()->GetPermissionManager())->permissionRequestReply(origin, type, reply); + static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())->permissionRequestReply(origin, type, reply); } -bool BrowserContextAdapter::checkPermission(const QUrl &origin, PermissionType type) +bool ProfileAdapter::checkPermission(const QUrl &origin, PermissionType type) { - return static_cast<PermissionManagerQt*>(browserContext()->GetPermissionManager())->checkPermission(origin, type); + return static_cast<PermissionManagerQt*>(profile()->GetPermissionControllerDelegate())->checkPermission(origin, type); } -QString BrowserContextAdapter::httpAcceptLanguageWithoutQualities() const +QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const { const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(',')); QString out; - Q_FOREACH (const QString& str, list) { + for (const QString &str : list) { if (!out.isEmpty()) out.append(QLatin1Char(',')); out.append(str.split(QLatin1Char(';')).first()); @@ -505,71 +477,71 @@ QString BrowserContextAdapter::httpAcceptLanguageWithoutQualities() const return out; } -QString BrowserContextAdapter::httpAcceptLanguage() const +QString ProfileAdapter::httpAcceptLanguage() const { return m_httpAcceptLanguage; } -void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) +void ProfileAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) { if (m_httpAcceptLanguage == httpAcceptLanguage) return; m_httpAcceptLanguage = httpAcceptLanguage; std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); - Q_FOREACH (content::WebContentsImpl *web_contents, list) { - if (web_contents->GetBrowserContext() == m_browserContext.data()) { + for (content::WebContentsImpl *web_contents : list) { + if (web_contents->GetBrowserContext() == m_profile.data()) { content::RendererPreferences* rendererPrefs = web_contents->GetMutableRendererPrefs(); rendererPrefs->accept_languages = httpAcceptLanguageWithoutQualities().toStdString(); web_contents->GetRenderViewHost()->SyncRendererPrefs(); } } - if (m_browserContext->url_request_getter_.get()) - m_browserContext->url_request_getter_->updateUserAgent(); + if (m_profile->m_urlRequestContextGetter.get()) + m_profile->m_profileIOData->updateUserAgent(); } -void BrowserContextAdapter::clearHttpCache() +void ProfileAdapter::clearHttpCache() { - content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_browserContext.data()); + content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_profile.data()); remover->Remove(base::Time(), base::Time::Max(), content::BrowsingDataRemover::DATA_TYPE_CACHE, content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); } -void BrowserContextAdapter::setSpellCheckLanguages(const QStringList &languages) +void ProfileAdapter::setSpellCheckLanguages(const QStringList &languages) { -#if BUILDFLAG(ENABLE_SPELLCHECK) - m_browserContext->setSpellCheckLanguages(languages); +#if QT_CONFIG(webengine_spellchecker) + m_profile->setSpellCheckLanguages(languages); #endif } -QStringList BrowserContextAdapter::spellCheckLanguages() const +QStringList ProfileAdapter::spellCheckLanguages() const { -#if BUILDFLAG(ENABLE_SPELLCHECK) - return m_browserContext->spellCheckLanguages(); +#if QT_CONFIG(webengine_spellchecker) + return m_profile->spellCheckLanguages(); #else return QStringList(); #endif } -void BrowserContextAdapter::setSpellCheckEnabled(bool enabled) +void ProfileAdapter::setSpellCheckEnabled(bool enabled) { -#if BUILDFLAG(ENABLE_SPELLCHECK) - m_browserContext->setSpellCheckEnabled(enabled); +#if QT_CONFIG(webengine_spellchecker) + m_profile->setSpellCheckEnabled(enabled); #endif } -bool BrowserContextAdapter::isSpellCheckEnabled() const +bool ProfileAdapter::isSpellCheckEnabled() const { -#if BUILDFLAG(ENABLE_SPELLCHECK) - return m_browserContext->isSpellCheckEnabled(); +#if QT_CONFIG(webengine_spellchecker) + return m_profile->isSpellCheckEnabled(); #else return false; #endif } -void BrowserContextAdapter::resetVisitedLinksManager() +void ProfileAdapter::resetVisitedLinksManager() { m_visitedLinksManager.reset(new VisitedLinksManagerQt(this)); } diff --git a/src/core/browser_context_adapter.h b/src/core/profile_adapter.h index b647bc30c..65843eda3 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/profile_adapter.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ -#ifndef BROWSER_CONTEXT_ADAPTER_H -#define BROWSER_CONTEXT_ADAPTER_H - -#include "qtwebenginecoreglobal.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. +// + +#ifndef PROFILE_ADAPTER_H +#define PROFILE_ADAPTER_H + +#include "qtwebenginecoreglobal_p.h" #include <QEnableSharedFromThis> #include <QList> @@ -57,24 +68,22 @@ QT_FORWARD_DECLARE_CLASS(QObject) namespace QtWebEngineCore { -class BrowserContextAdapterClient; -class BrowserContextQt; +class ProfileAdapterClient; class DownloadManagerDelegateQt; +class ProfileQt; class UserResourceControllerHost; class VisitedLinksManagerQt; -class QWEBENGINE_EXPORT BrowserContextAdapter : public QEnableSharedFromThis<BrowserContextAdapter> +class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject { public: - explicit BrowserContextAdapter(bool offTheRecord = false); - explicit BrowserContextAdapter(const QString &storagePrefix); - virtual ~BrowserContextAdapter(); + explicit ProfileAdapter(const QString &storagePrefix = QString()); + virtual ~ProfileAdapter(); - static QSharedPointer<BrowserContextAdapter> defaultContext(); + static ProfileAdapter* createDefaultProfileAdapter(); + static ProfileAdapter* defaultProfileAdapter(); static QObject* globalQObjectRoot(); - void shutdown(); - VisitedLinksManagerQt *visitedLinksManager(); DownloadManagerDelegateQt *downloadManagerDelegate(); @@ -83,15 +92,15 @@ public: QWebEngineUrlRequestInterceptor* requestInterceptor(); void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); - QList<BrowserContextAdapterClient*> clients() { return m_clients; } - void addClient(BrowserContextAdapterClient *adapterClient); - void removeClient(BrowserContextAdapterClient *adapterClient); + QList<ProfileAdapterClient*> clients() { return m_clients; } + void addClient(ProfileAdapterClient *adapterClient); + void removeClient(ProfileAdapterClient *adapterClient); void cancelDownload(quint32 downloadId); void pauseDownload(quint32 downloadId); void resumeDownload(quint32 downloadId); - BrowserContextQt *browserContext(); + ProfileQt *profile(); QString storageName() const { return m_name; } void setStorageName(const QString &storageName); @@ -146,13 +155,13 @@ public: }; HttpCacheType httpCacheType() const; - void setHttpCacheType(BrowserContextAdapter::HttpCacheType); + void setHttpCacheType(ProfileAdapter::HttpCacheType); PersistentCookiesPolicy persistentCookiesPolicy() const; - void setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy); + void setPersistentCookiesPolicy(ProfileAdapter::PersistentCookiesPolicy); VisitedLinksPolicy visitedLinksPolicy() const; - void setVisitedLinksPolicy(BrowserContextAdapter::VisitedLinksPolicy); + void setVisitedLinksPolicy(ProfileAdapter::VisitedLinksPolicy); int httpCacheMaxSize() const; void setHttpCacheMaxSize(int maxSize); @@ -183,7 +192,7 @@ private: QString m_name; bool m_offTheRecord; - QScopedPointer<BrowserContextQt> m_browserContext; + QScopedPointer<ProfileQt> m_profile; QScopedPointer<VisitedLinksManagerQt> m_visitedLinksManager; QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate; QScopedPointer<UserResourceControllerHost> m_userResourceController; @@ -198,12 +207,12 @@ private: PersistentCookiesPolicy m_persistentCookiesPolicy; VisitedLinksPolicy m_visitedLinksPolicy; QHash<QByteArray, QWebEngineUrlSchemeHandler *> m_customUrlSchemeHandlers; - QList<BrowserContextAdapterClient*> m_clients; + QList<ProfileAdapterClient*> m_clients; int m_httpCacheMaxSize; - Q_DISABLE_COPY(BrowserContextAdapter) + Q_DISABLE_COPY(ProfileAdapter) }; } // namespace QtWebEngineCore -#endif // BROWSER_CONTEXT_ADAPTER_H +#endif // PROFILE_ADAPTER_H diff --git a/src/core/browser_context_adapter_client.cpp b/src/core/profile_adapter_client.cpp index 3a7447686..9aa084da9 100644 --- a/src/core/browser_context_adapter_client.cpp +++ b/src/core/profile_adapter_client.cpp @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#include "browser_context_adapter_client.h" -#include "content/public/browser/download_item.h" +#include "profile_adapter_client.h" +#include "components/download/public/common/download_item.h" #include "content/public/browser/save_page_type.h" #include <QCoreApplication> @@ -46,45 +46,45 @@ 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(download::DownloadItem::IN_PROGRESS, ProfileAdapterClient::DownloadInProgress) +ASSERT_ENUMS_MATCH(download::DownloadItem::COMPLETE, ProfileAdapterClient::DownloadCompleted) +ASSERT_ENUMS_MATCH(download::DownloadItem::CANCELLED, ProfileAdapterClient::DownloadCancelled) +ASSERT_ENUMS_MATCH(download::DownloadItem::INTERRUPTED, ProfileAdapterClient::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::SAVE_PAGE_TYPE_UNKNOWN, ProfileAdapterClient::UnknownSavePageFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_ONLY_HTML, ProfileAdapterClient::SingleHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, ProfileAdapterClient::CompleteHtmlSaveFormat) +ASSERT_ENUMS_MATCH(content::SAVE_PAGE_TYPE_AS_MHTML, ProfileAdapterClient::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) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NONE, ProfileAdapterClient::NoReason) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, ProfileAdapterClient::FileFailed) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, ProfileAdapterClient::FileAccessDenied) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE, ProfileAdapterClient::FileNoSpace) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG, ProfileAdapterClient::FileNameTooLong) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE, ProfileAdapterClient::FileTooLarge) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED, ProfileAdapterClient::FileVirusInfected) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, ProfileAdapterClient::FileTransientError) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED, ProfileAdapterClient::FileBlocked) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED, ProfileAdapterClient::FileSecurityCheckFailed) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT, ProfileAdapterClient::FileTooShort) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH, ProfileAdapterClient::FileHashMismatch) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, ProfileAdapterClient::NetworkFailed) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, ProfileAdapterClient::NetworkTimeout) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, ProfileAdapterClient::NetworkDisconnected) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN, ProfileAdapterClient::NetworkServerDown) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, ProfileAdapterClient::NetworkInvalidRequest) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, ProfileAdapterClient::ServerFailed) +//ASSERT_ENUMS_MATCH(content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE, ProfileAdapterClient::ServerNoRange) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, ProfileAdapterClient::ServerBadContent) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED, ProfileAdapterClient::ServerUnauthorized) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM, ProfileAdapterClient::ServerCertProblem) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN, ProfileAdapterClient::ServerForbidden) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE, ProfileAdapterClient::ServerUnreachable) +ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED, ProfileAdapterClient::UserCanceled) +//ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN, ProfileAdapterClient::UserShutdown) +//ASSERT_ENUMS_MATCH(download::DOWNLOAD_INTERRUPT_REASON_CRASH, ProfileAdapterClient::Crash) -QString BrowserContextAdapterClient::downloadInterruptReasonToString(DownloadInterruptReason reason) +QString ProfileAdapterClient::downloadInterruptReasonToString(DownloadInterruptReason reason) { switch (reason) { default: diff --git a/src/core/browser_context_adapter_client.h b/src/core/profile_adapter_client.h index 02bee8ed6..06051fab6 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -37,16 +37,29 @@ ** ****************************************************************************/ -#ifndef BROWSER_CONTEXT_ADAPTER_CLIENT_H -#define BROWSER_CONTEXT_ADAPTER_CLIENT_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 "qtwebenginecoreglobal.h" +#ifndef PROFILE_ADAPTER_CLIENT_H +#define PROFILE_ADAPTER_CLIENT_H + +#include "qtwebenginecoreglobal_p.h" #include <QString> #include <QUrl> namespace QtWebEngineCore { -class QWEBENGINE_EXPORT BrowserContextAdapterClient +class WebContentsAdapterClient; + +class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapterClient { public: // Keep in sync with content::DownloadItem::DownloadState @@ -122,9 +135,10 @@ public: bool done; int downloadType; int downloadInterruptReason; + WebContentsAdapterClient *page; }; - virtual ~BrowserContextAdapterClient() { } + virtual ~ProfileAdapterClient() { } virtual void downloadRequested(DownloadItemInfo &info) = 0; virtual void downloadUpdated(const DownloadItemInfo &info) = 0; @@ -133,4 +147,4 @@ public: } // namespace -#endif // BROWSER_CONTEXT_ADAPTER_CLIENT_H +#endif // PROFILE_ADAPTER_CLIENT_H diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp new file mode 100644 index 000000000..7aaddc35a --- /dev/null +++ b/src/core/profile_io_data_qt.cpp @@ -0,0 +1,696 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "profile_io_data_qt.h" + +#include "base/task_scheduler/post_task.h" +#include "components/certificate_transparency/ct_known_logs.h" +#include "components/network_session_configurator/common/network_features.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/browsing_data_remover.h" +#include "content/public/browser/cookie_store_factory.h" +#include "content/public/common/content_features.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" +#include "net/cert/multi_log_ct_verifier.h" +#include "net/extras/sqlite/sqlite_channel_id_store.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_auth_scheme.h" +#include "net/http/http_auth_preferences.h" +#include "net/http/http_cache.h" +#include "net/http/http_server_properties_impl.h" +#include "net/http/http_network_session.h" +#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h" +#include "net/proxy_resolution/pac_file_fetcher_impl.h" +#include "net/proxy_resolution/proxy_config_service.h" +#include "net/proxy_resolution/proxy_resolution_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/ftp_protocol_handler.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "services/file/user_id_map.h" +#include "services/network/proxy_service_mojo.h" + +#include "net/cookie_monster_delegate_qt.h" +#include "net/custom_protocol_handler.h" +#include "net/network_delegate_qt.h" +#include "net/proxy_config_service_qt.h" +#include "net/qrc_protocol_handler_qt.h" +#include "net/url_request_context_getter_qt.h" +#include "profile_qt.h" +#include "resource_context_qt.h" +#include "type_conversion.h" + +namespace QtWebEngineCore { + +static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme, + net::kDigestAuthScheme, +#if QT_CONFIG(webengine_kerberos) + net::kNegotiateAuthScheme, +#endif + net::kNtlmAuthScheme }; + +static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, + const net::HttpNetworkSession::Params &second) +{ + if (first.ignore_certificate_errors != second.ignore_certificate_errors) + return false; + if (first.enable_channel_id != second.enable_channel_id) + return false; + if (first.enable_token_binding != second.enable_token_binding) + return false; + return true; +} + +static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, + const net::HttpNetworkSession::Context &second) +{ + if (first.transport_security_state != second.transport_security_state) + return false; + if (first.cert_verifier != second.cert_verifier) + return false; + if (first.channel_id_service != second.channel_id_service) + return false; + if (first.proxy_resolution_service != second.proxy_resolution_service) + return false; + if (first.ssl_config_service != second.ssl_config_service) + return false; + if (first.http_auth_handler_factory != second.http_auth_handler_factory) + return false; + if (first.http_server_properties != second.http_server_properties) + return false; + if (first.host_resolver != second.host_resolver) + return false; + if (first.cert_transparency_verifier != second.cert_transparency_verifier) + return false; + if (first.ct_policy_enforcer != second.ct_policy_enforcer) + return false; + return true; +} + +static net::HttpNetworkSession::Context generateNetworkSessionContext(net::URLRequestContext *urlRequestContext) +{ + net::HttpNetworkSession::Context network_session_context; + network_session_context.transport_security_state = urlRequestContext->transport_security_state(); + network_session_context.cert_verifier = urlRequestContext->cert_verifier(); + network_session_context.channel_id_service = urlRequestContext->channel_id_service(); + network_session_context.proxy_resolution_service = urlRequestContext->proxy_resolution_service(); + network_session_context.ssl_config_service = urlRequestContext->ssl_config_service(); + network_session_context.http_auth_handler_factory = urlRequestContext->http_auth_handler_factory(); + network_session_context.http_server_properties = urlRequestContext->http_server_properties(); + network_session_context.host_resolver = urlRequestContext->host_resolver(); + network_session_context.cert_transparency_verifier = urlRequestContext->cert_transparency_verifier(); + network_session_context.ct_policy_enforcer = urlRequestContext->ct_policy_enforcer(); + return network_session_context; +} + +static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreCertificateErrors) +{ + net::HttpNetworkSession::Params network_session_params; + network_session_params.ignore_certificate_errors = ignoreCertificateErrors; + network_session_params.enable_token_binding = base::FeatureList::IsEnabled(features::kTokenBinding); + network_session_params.enable_channel_id = base::FeatureList::IsEnabled(features::kChannelID); + return network_session_params; +} + +ProfileIODataQt::ProfileIODataQt(ProfileQt *profile) + : m_profile(profile), + m_mutex(QMutex::Recursive), + m_weakPtrFactory(this) +{ + if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI)) + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} + +ProfileIODataQt::~ProfileIODataQt() +{ + if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO)) + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + m_resourceContext.reset(); + if (m_cookieDelegate) + m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted + m_networkDelegate.reset(); + delete m_proxyConfigService.fetchAndStoreAcquire(0); +} + +void ProfileIODataQt::shutdownOnUIThread() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this); + if (!posted) { + qWarning() << "Could not delete ProfileIODataQt on io thread !"; + delete this; + } +} + +net::URLRequestContext *ProfileIODataQt::urlRequestContext() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_initialized) + initializeOnIOThread(); + return m_urlRequestContext.get(); +} + +content::ResourceContext *ProfileIODataQt::resourceContext() +{ + return m_resourceContext.get(); +} + +void ProfileIODataQt::initializeOnIOThread() +{ + m_networkDelegate.reset(new NetworkDelegateQt(this)); + m_urlRequestContext.reset(new net::URLRequestContext()); + m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); + m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding)); + // this binds factory to io thread + m_weakPtr = m_weakPtrFactory.GetWeakPtr(); + QMutexLocker lock(&m_mutex); + m_initialized = true; + generateAllStorage(); + generateJobFactory(); +} + +void ProfileIODataQt::initializeOnUIThread() +{ + m_profileAdapter = m_profile->profileAdapter(); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + m_resourceContext.reset(new ResourceContextQt(this)); + ProtocolHandlerRegistry* protocolHandlerRegistry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(m_profile); + DCHECK(protocolHandlerRegistry); + m_protocolHandlerInterceptor = + protocolHandlerRegistry->CreateJobInterceptorFactory(); + m_cookieDelegate = new CookieMonsterDelegateQt(); + m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore()); +} + +void ProfileIODataQt::cancelAllUrlRequests() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + + const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests(); + std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); + std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); + for ( ; it != end; ++it) { + net::URLRequest* request = const_cast<net::URLRequest*>(*it); + if (request) + request->Cancel(); + } +} + +void ProfileIODataQt::generateAllStorage() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + QMutexLocker lock(&m_mutex); + generateStorage(); + generateCookieStore(); + generateUserAgent(); + generateHttpCache(); + m_updateAllStorage = false; +} + +void ProfileIODataQt::generateStorage() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + + // We must stop all requests before deleting their backends. + if (m_storage) { + m_cookieDelegate->setCookieMonster(0); + m_storage->set_cookie_store(0); + cancelAllUrlRequests(); + // we need to get rid of dangling pointer due to coming storage deletion + m_urlRequestContext->set_http_transaction_factory(0); + m_httpNetworkSession.reset(); + } + + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); + + net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); + Q_ASSERT(proxyConfigService); + + m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); + std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); +// FIXME: +// ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); + m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); + m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer())); + + std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); + + // The System Proxy Resolver has issues on Windows with unconfigured network cards, + // which is why we want to use the v8 one + if (!m_dhcpPacFileFetcherFactory) + m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory); + + proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface)); + m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory( + std::move(proxyResolver), + std::unique_ptr<net::ProxyConfigService>(proxyConfigService), + net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()), + m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()), + host_resolver.get(), + nullptr /* NetLog */, + m_networkDelegate.get())); + + m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>()); + m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>( + new net::TransportSecurityState())); + + if (!m_httpAuthPreferences) + m_httpAuthPreferences.reset(new net::HttpAuthPreferences()); + + m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( + host_resolver.get(), + m_httpAuthPreferences.get() +#if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) + , std::string() /* gssapi library name */ +#endif + )); + m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>( + new net::HttpServerPropertiesImpl)); + // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. + m_storage->set_host_resolver(std::move(host_resolver)); +} + + +void ProfileIODataQt::generateCookieStore() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateCookieStore = false; + + scoped_refptr<net::SQLiteChannelIDStore> channel_id_db; + if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies) { + channel_id_db = new net::SQLiteChannelIDStore( + toFilePath(m_channelIdPath), + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND})); + } + + m_storage->set_channel_id_service( + base::WrapUnique(new net::ChannelIDService( + new net::DefaultChannelIDStore(channel_id_db.get())))); + + // Unset it first to get a chance to destroy and flush the old cookie store before + // opening a new on possibly the same file. + m_cookieDelegate->setCookieMonster(0); + m_storage->set_cookie_store(0); + + std::unique_ptr<net::CookieStore> cookieStore; + switch (m_persistentCookiesPolicy) { + case ProfileAdapter::NoPersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + base::FilePath(), + false, + false, + nullptr) + ); + break; + case ProfileAdapter::AllowPersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + toFilePath(m_cookiesPath), + false, + true, + nullptr) + ); + break; + case ProfileAdapter::ForcePersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + toFilePath(m_cookiesPath), + true, + true, + nullptr) + ); + break; + } + + net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get()); + cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID()); + m_cookieDelegate->setCookieMonster(cookieMonster); + m_storage->set_cookie_store(std::move(cookieStore)); + + const std::vector<std::string> cookieableSchemes(kCookieableSchemes, + kCookieableSchemes + arraysize(kCookieableSchemes)); + cookieMonster->SetCookieableSchemes(cookieableSchemes); + + if (!m_updateAllStorage && m_updateHttpCache) { + // HttpCache needs to be regenerated when we generate a new channel id service + generateHttpCache(); + } +} + +void ProfileIODataQt::generateUserAgent() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateUserAgent = false; + + m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( + new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), + m_httpUserAgent.toStdString()))); +} + +void ProfileIODataQt::generateHttpCache() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateHttpCache = false; + + if (m_updateCookieStore) + generateCookieStore(); + + net::HttpCache::DefaultBackend* main_backend = 0; + switch (m_httpCacheType) { + case ProfileAdapter::MemoryHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::MEMORY_CACHE, + net::CACHE_BACKEND_DEFAULT, + base::FilePath(), + m_httpCacheMaxSize + ); + break; + case ProfileAdapter::DiskHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + toFilePath(m_httpCachePath), + m_httpCacheMaxSize + ); + break; + case ProfileAdapter::NoCache: + // It's safe to not create BackendFactory. + break; + } + + net::HttpCache *cache = 0; + net::HttpNetworkSession::Context network_session_context = + generateNetworkSessionContext(m_urlRequestContext.get()); + net::HttpNetworkSession::Params network_session_params = + generateNetworkSessionParams(m_ignoreCertificateErrors); + + if (!m_httpNetworkSession + || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) + || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { + cancelAllUrlRequests(); + m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, + network_session_context)); + } + + cache = new net::HttpCache(m_httpNetworkSession.get(), + std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false); + + m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); +} + +void ProfileIODataQt::generateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(!m_jobFactory); + + QMutexLocker lock(&m_mutex); + m_updateJobFactory = false; + + std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); + for (auto &it : m_protocolHandlers) + jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release())); + m_protocolHandlers.clear(); + + jobFactory->SetProtocolHandler(url::kDataScheme, + std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( + new net::DataProtocolHandler())); + scoped_refptr<base::TaskRunner> taskRunner(base::CreateTaskRunnerWithTraits({base::MayBlock(), + base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); + jobFactory->SetProtocolHandler(url::kFileScheme, + std::make_unique<net::FileProtocolHandler>(taskRunner)); + jobFactory->SetProtocolHandler(kQrcSchemeQt, + std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( + new QrcProtocolHandlerQt())); + jobFactory->SetProtocolHandler(url::kFtpScheme, + net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver())); + + m_installedCustomSchemes = m_customUrlSchemes; + for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { + jobFactory->SetProtocolHandler(scheme.toStdString(), + std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( + new CustomProtocolHandler(m_profileAdapter))); + } + + m_baseJobFactory = jobFactory.get(); + + // Set up interceptors in the reverse order. + std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); + content::URLRequestInterceptorScopedVector::reverse_iterator i; + for (i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { + topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), + std::move(*i))); + } + + m_requestInterceptors.clear(); + + if (m_protocolHandlerInterceptor) { + m_protocolHandlerInterceptor->Chain(std::move(topJobFactory)); + topJobFactory = std::move(m_protocolHandlerInterceptor); + } + + m_jobFactory = std::move(topJobFactory); + + m_urlRequestContext->set_job_factory(m_jobFactory.get()); +} + +void ProfileIODataQt::regenerateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_jobFactory); + Q_ASSERT(m_baseJobFactory); + + QMutexLocker lock(&m_mutex); + m_updateJobFactory = false; + + if (m_customUrlSchemes == m_installedCustomSchemes) + return; + + for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); + } + + m_installedCustomSchemes = m_customUrlSchemes; + for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), + std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>( + new CustomProtocolHandler(m_profileAdapter))); + } +} + +void ProfileIODataQt::setRequestContextData(content::ProtocolHandlerMap *protocolHandlers, + content::URLRequestInterceptorScopedVector request_interceptors) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + Q_ASSERT(!m_initialized); + m_requestInterceptors = std::move(request_interceptors); + std::swap(m_protocolHandlers, *protocolHandlers); +} + +void ProfileIODataQt::setFullConfiguration() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + m_requestInterceptor = m_profileAdapter->requestInterceptor(); + m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); + m_cookiesPath = m_profileAdapter->cookiesPath(); + m_channelIdPath = m_profileAdapter->channelIdPath(); + m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); + m_httpUserAgent = m_profileAdapter->httpUserAgent(); + m_httpCacheType = m_profileAdapter->httpCacheType(); + m_httpCachePath = m_profileAdapter->httpCachePath(); + m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize(); + m_customUrlSchemes = m_profileAdapter->customUrlSchemes(); +} + +void ProfileIODataQt::updateStorageSettings() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + QMutexLocker lock(&m_mutex); + setFullConfiguration(); + + std::string userId = content::BrowserContext::GetServiceUserIdFor(m_profile); + if (file::GetUserDirForUserId(userId) != toFilePath(m_profileAdapter->dataPath())) { + file::ForgetServiceUserIdUserDirAssociation(userId); + file::AssociateServiceUserIdWithUserDir(userId, toFilePath(m_profileAdapter->dataPath())); + } + + if (!m_updateAllStorage) { + m_updateAllStorage = true; + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). + Q_ASSERT(m_proxyConfigService == 0); + m_proxyConfigService = + new ProxyConfigServiceQt( + net::ProxyResolutionService::CreateSystemProxyConfigService( + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO))); + //pass interface to io thread + m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface(); + if (m_initialized) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&ProfileIODataQt::generateAllStorage, m_weakPtr)); + } +} + +void ProfileIODataQt::updateCookieStore() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); + m_cookiesPath = m_profileAdapter->cookiesPath(); + m_channelIdPath = m_profileAdapter->channelIdPath(); + + if (m_initialized && !m_updateAllStorage && !m_updateCookieStore) { + m_updateCookieStore = true; + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&ProfileIODataQt::generateCookieStore, m_weakPtr)); + } +} + +void ProfileIODataQt::updateUserAgent() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); + m_httpUserAgent = m_profileAdapter->httpUserAgent(); + + if (m_initialized && !m_updateAllStorage && !m_updateUserAgent) { + m_updateUserAgent = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&ProfileIODataQt::generateUserAgent, m_weakPtr)); + } +} + +void ProfileIODataQt::updateHttpCache() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_httpCacheType = m_profileAdapter->httpCacheType(); + m_httpCachePath = m_profileAdapter->httpCachePath(); + m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize(); + + if (m_httpCacheType == ProfileAdapter::NoCache) { + content::BrowsingDataRemover *remover = + content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile()); + remover->Remove(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_CACHE, + content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | + content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); + } + + if (m_initialized && !m_updateAllStorage && !m_updateHttpCache) { + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&ProfileIODataQt::generateHttpCache, m_weakPtr)); + } +} + +void ProfileIODataQt::updateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + + m_customUrlSchemes = m_profileAdapter->customUrlSchemes(); + + if (m_initialized && !m_updateJobFactory) { + m_updateJobFactory = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&ProfileIODataQt::regenerateJobFactory, m_weakPtr)); + } +} + +void ProfileIODataQt::updateRequestInterceptor() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_requestInterceptor = m_profileAdapter->requestInterceptor(); + // We in this case do not need to regenerate any Chromium classes. +} + +QWebEngineUrlRequestInterceptor *ProfileIODataQt::requestInterceptor() +{ + // used in NetworkDelegateQt::OnBeforeURLRequest + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + QMutexLocker lock(&m_mutex); + return m_requestInterceptor; +} + +bool ProfileIODataQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const +{ + return m_cookieDelegate->canSetCookie(firstPartyUrl,cookieLine, url); +} + +bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const +{ + return m_cookieDelegate->canGetCookies(firstPartyUrl, url); +} + +} // namespace QtWebEngineCore diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h new file mode 100644 index 000000000..60f4d2d1e --- /dev/null +++ b/src/core/profile_io_data_qt.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 PROFILE_IO_DATA_QT_H +#define PROFILE_IO_DATA_QT_H + +#include "profile_adapter.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" + +#include <QtCore/QString> +#include <QtCore/QPointer> +#include <QtCore/QMutex> + +namespace net { +class DhcpPacFileFetcherFactory; +class HttpAuthPreferences; +class HttpNetworkSession; +class NetworkDelegate; +class ProxyConfigService; +class URLRequestContext; +class URLRequestContextStorage; +class URLRequestJobFactoryImpl; +} + +namespace QtWebEngineCore { + +class ProfileQt; + +// ProfileIOData contains data that lives on the IOthread +// we still use shared memebers and use mutex which breaks +// idea for this object, but this is wip. + +class ProfileIODataQt { + +public: + ProfileIODataQt(ProfileQt *profile); // runs on ui thread + virtual ~ProfileIODataQt(); + + content::ResourceContext *resourceContext(); + net::URLRequestContext *urlRequestContext(); + void initializeOnIOThread(); + void initializeOnUIThread(); // runs on ui thread + void shutdownOnUIThread(); // runs on ui thread + + void cancelAllUrlRequests(); + void generateAllStorage(); + void generateStorage(); + void generateCookieStore(); + void generateHttpCache(); + void generateUserAgent(); + void generateJobFactory(); + void regenerateJobFactory(); + QWebEngineUrlRequestInterceptor *requestInterceptor(); + bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; + bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; + + void setRequestContextData(content::ProtocolHandlerMap *protocolHandlers, + content::URLRequestInterceptorScopedVector request_interceptors); + void setFullConfiguration(); // runs on ui thread + void updateStorageSettings(); // runs on ui thread + void updateUserAgent(); // runs on ui thread + void updateCookieStore(); // runs on ui thread + void updateHttpCache(); // runs on ui thread + void updateJobFactory(); // runs on ui thread + void updateRequestInterceptor(); // runs on ui thread + +private: + ProfileQt *m_profile; + std::unique_ptr<net::URLRequestContextStorage> m_storage; + std::unique_ptr<net::NetworkDelegate> m_networkDelegate; + std::unique_ptr<content::ResourceContext> m_resourceContext; + std::unique_ptr<net::URLRequestContext> m_urlRequestContext; + std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; + std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> m_protocolHandlerInterceptor; + std::unique_ptr<net::DhcpPacFileFetcherFactory> m_dhcpPacFileFetcherFactory; + std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; + std::unique_ptr<net::URLRequestJobFactory> m_jobFactory; + base::WeakPtr<ProfileIODataQt> m_weakPtr; + scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; + content::URLRequestInterceptorScopedVector m_requestInterceptors; + content::ProtocolHandlerMap m_protocolHandlers; + mojo::InterfacePtrInfo<proxy_resolver::mojom::ProxyResolverFactory> m_proxyResolverFactoryInterface; + net::URLRequestJobFactoryImpl *m_baseJobFactory = nullptr; + QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; + QPointer<ProfileAdapter> m_profileAdapter; // never dereferenced in IO thread and it is passed by qpointer + ProfileAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; + QString m_cookiesPath; + QString m_channelIdPath; + QString m_httpAcceptLanguage; + QString m_httpUserAgent; + ProfileAdapter::HttpCacheType m_httpCacheType; + QString m_httpCachePath; + QList<QByteArray> m_customUrlSchemes; + QList<QByteArray> m_installedCustomSchemes; + QWebEngineUrlRequestInterceptor* m_requestInterceptor = nullptr; + QMutex m_mutex; + int m_httpCacheMaxSize = 0; + bool m_initialized = false; + bool m_updateAllStorage = false; + bool m_updateCookieStore = false; + bool m_updateHttpCache = false; + bool m_updateJobFactory = false; + bool m_updateUserAgent = false; + bool m_ignoreCertificateErrors = false; + base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member + DISALLOW_COPY_AND_ASSIGN(ProfileIODataQt); +}; +} // namespace QtWebEngineCore + +#endif // PROFILE_IO_DATA_QT_H diff --git a/src/core/browser_context_qt.cpp b/src/core/profile_qt.cpp index 96bfde443..df05d891e 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/profile_qt.cpp @@ -37,25 +37,24 @@ ** ****************************************************************************/ -#include "browser_context_qt.h" +#include "profile_qt.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "browsing_data_remover_delegate_qt.h" #include "download_manager_delegate_qt.h" #include "net/ssl_host_state_delegate_qt.h" #include "net/url_request_context_getter_qt.h" #include "permission_manager_qt.h" #include "qtwebenginecoreglobal_p.h" -#include "resource_context_qt.h" #include "type_conversion.h" #include "web_engine_library_info.h" #include "base/time/time.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" -#include "net/proxy/proxy_config_service.h" #include "base/base_paths.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" #include "components/prefs/in_memory_pref_store.h" @@ -63,7 +62,7 @@ #include "components/prefs/pref_service_factory.h" #include "components/prefs/pref_registry_simple.h" #include "components/user_prefs/user_prefs.h" -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/common/pref_names.h" #include "components/spellcheck/browser/pref_names.h" @@ -71,137 +70,153 @@ namespace QtWebEngineCore { -BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter) - : m_adapter(adapter) +ProfileQt::ProfileQt(ProfileAdapter *profileAdapter) + : m_profileIOData(new ProfileIODataQt(this)), + m_profileAdapter(profileAdapter) { PrefServiceFactory factory; factory.set_user_prefs(new InMemoryPrefStore); PrefRegistrySimple *registry = new PrefRegistrySimple(); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) // Initial spellcheck settings registry->RegisterStringPref(prefs::kAcceptLanguages, std::string()); - registry->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries, base::MakeUnique<base::ListValue>()); - registry->RegisterListPref(spellcheck::prefs::kSpellCheckForcedDictionaries, base::MakeUnique<base::ListValue>()); + registry->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries, std::make_unique<base::ListValue>()); + registry->RegisterListPref(spellcheck::prefs::kSpellCheckForcedDictionaries, std::make_unique<base::ListValue>()); registry->RegisterStringPref(spellcheck::prefs::kSpellCheckDictionary, std::string()); registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckEnable, false); registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckUseSpellingService, false); -#endif //ENABLE_SPELLCHECK +#endif // QT_CONFIG(webengine_spellchecker) m_prefService = factory.Create(registry); user_prefs::UserPrefs::Set(this, m_prefService.get()); + + // Mark the context as live. This prevents the use-after-free DCHECK in + // AssertBrowserContextWasntDestroyed from being triggered when a new + // ProfileQt object is allocated at the same address as a previously + // destroyed one. Needs to be called after WebEngineContext initialization. + BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(this); } -BrowserContextQt::~BrowserContextQt() +ProfileQt::~ProfileQt() { - if (resourceContext) - content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, resourceContext.release()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::BrowserContext::NotifyWillBeDestroyed(this); + BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(this); + ShutdownStoragePartitions(); + m_profileIOData->shutdownOnUIThread(); + //Should be deleted by IO Thread + m_profileIOData.release(); } -PrefService* BrowserContextQt::GetPrefs() +PrefService* ProfileQt::GetPrefs() { return m_prefService.get(); } -const PrefService* BrowserContextQt::GetPrefs() const +const PrefService* ProfileQt::GetPrefs() const { return m_prefService.get(); } -base::FilePath BrowserContextQt::GetPath() const +base::FilePath ProfileQt::GetPath() const { - return toFilePath(m_adapter->dataPath()); + return toFilePath(m_profileAdapter->dataPath()); } -bool BrowserContextQt::IsOffTheRecord() const +bool ProfileQt::IsOffTheRecord() const { - return m_adapter->isOffTheRecord(); + return m_profileAdapter->isOffTheRecord(); } -net::URLRequestContextGetter *BrowserContextQt::GetRequestContext() +net::URLRequestContextGetter *ProfileQt::GetRequestContext() { - return url_request_getter_.get(); + return m_urlRequestContextGetter.get(); } -net::URLRequestContextGetter *BrowserContextQt::CreateMediaRequestContext() +net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContext() { - return url_request_getter_.get(); + return m_urlRequestContextGetter.get(); } -net::URLRequestContextGetter *BrowserContextQt::CreateMediaRequestContextForStoragePartition(const base::FilePath&, bool) +net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContextForStoragePartition(const base::FilePath&, bool) { Q_UNIMPLEMENTED(); return nullptr; } -content::ResourceContext *BrowserContextQt::GetResourceContext() +content::ResourceContext *ProfileQt::GetResourceContext() { - if (!resourceContext) - resourceContext.reset(new ResourceContextQt(this)); - return resourceContext.get(); + return m_profileIOData->resourceContext(); } -content::DownloadManagerDelegate *BrowserContextQt::GetDownloadManagerDelegate() +content::DownloadManagerDelegate *ProfileQt::GetDownloadManagerDelegate() { - return m_adapter->downloadManagerDelegate(); + return m_profileAdapter->downloadManagerDelegate(); } -content::BrowserPluginGuestManager *BrowserContextQt::GetGuestManager() +content::BrowserPluginGuestManager *ProfileQt::GetGuestManager() { - return 0; + return nullptr; } -storage::SpecialStoragePolicy *BrowserContextQt::GetSpecialStoragePolicy() +storage::SpecialStoragePolicy *ProfileQt::GetSpecialStoragePolicy() { QT_NOT_YET_IMPLEMENTED - return 0; + return nullptr; } -content::PushMessagingService *BrowserContextQt::GetPushMessagingService() +content::PushMessagingService *ProfileQt::GetPushMessagingService() { - return 0; + return nullptr; } -content::SSLHostStateDelegate* BrowserContextQt::GetSSLHostStateDelegate() +content::SSLHostStateDelegate* ProfileQt::GetSSLHostStateDelegate() { - if (!sslHostStateDelegate) - sslHostStateDelegate.reset(new SSLHostStateDelegateQt()); - return sslHostStateDelegate.get(); + if (!m_sslHostStateDelegate) + m_sslHostStateDelegate.reset(new SSLHostStateDelegateQt()); + return m_sslHostStateDelegate.get(); } -std::unique_ptr<content::ZoomLevelDelegate> BrowserContextQt::CreateZoomLevelDelegate(const base::FilePath&) +std::unique_ptr<content::ZoomLevelDelegate> ProfileQt::CreateZoomLevelDelegate(const base::FilePath&) { return nullptr; } -content::BackgroundFetchDelegate* BrowserContextQt::GetBackgroundFetchDelegate() +content::BackgroundFetchDelegate* ProfileQt::GetBackgroundFetchDelegate() { return nullptr; } -content::BackgroundSyncController* BrowserContextQt::GetBackgroundSyncController() +content::BackgroundSyncController* ProfileQt::GetBackgroundSyncController() { return nullptr; } -content::BrowsingDataRemoverDelegate *BrowserContextQt::GetBrowsingDataRemoverDelegate() +content::BrowsingDataRemoverDelegate *ProfileQt::GetBrowsingDataRemoverDelegate() { - return new BrowsingDataRemoverDelegateQt; + return new BrowsingDataRemoverDelegateQt(); } -content::PermissionManager *BrowserContextQt::GetPermissionManager() +content::PermissionControllerDelegate *ProfileQt::GetPermissionControllerDelegate() { - if (!permissionManager) - permissionManager.reset(new PermissionManagerQt()); - return permissionManager.get(); + if (!m_permissionManager) + m_permissionManager.reset(new PermissionManagerQt()); + return m_permissionManager.get(); } -net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) +net::URLRequestContextGetter *ProfileQt::CreateRequestContext( + content::ProtocolHandlerMap *protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { - url_request_getter_ = new URLRequestContextGetterQt(m_adapter->sharedFromThis(), protocol_handlers, std::move(request_interceptors)); - return url_request_getter_.get(); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(!m_urlRequestContextGetter.get()); + m_profileIOData->setRequestContextData(protocol_handlers, std::move(request_interceptors)); + m_profileIOData->updateStorageSettings(); + m_urlRequestContextGetter = new URLRequestContextGetterQt(m_profileIOData.get()); + return m_urlRequestContextGetter.get(); } -net::URLRequestContextGetter *BrowserContextQt::CreateRequestContextForStoragePartition( +net::URLRequestContextGetter *ProfileQt::CreateRequestContextForStoragePartition( const base::FilePath& partition_path, bool in_memory, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) @@ -210,15 +225,15 @@ net::URLRequestContextGetter *BrowserContextQt::CreateRequestContextForStoragePa return nullptr; } -#if BUILDFLAG(ENABLE_SPELLCHECK) -void BrowserContextQt::FailedToLoadDictionary(const std::string &language) +#if QT_CONFIG(webengine_spellchecker) +void ProfileQt::FailedToLoadDictionary(const std::string &language) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); qWarning() << "Could not load dictionary for:" << toQt(language) << endl << "Make sure that correct bdic file is in:" << toQt(WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES).value()); } -void BrowserContextQt::setSpellCheckLanguages(const QStringList &languages) +void ProfileQt::setSpellCheckLanguages(const QStringList &languages) { StringListPrefMember dictionaries_pref; dictionaries_pref.Init(spellcheck::prefs::kSpellCheckDictionaries, m_prefService.get()); @@ -229,7 +244,7 @@ void BrowserContextQt::setSpellCheckLanguages(const QStringList &languages) dictionaries_pref.SetValue(dictionaries); } -QStringList BrowserContextQt::spellCheckLanguages() const +QStringList ProfileQt::spellCheckLanguages() const { QStringList spellcheck_dictionaries; for (const auto &value : *m_prefService->GetList(spellcheck::prefs::kSpellCheckDictionaries)) { @@ -241,14 +256,14 @@ QStringList BrowserContextQt::spellCheckLanguages() const return spellcheck_dictionaries; } -void BrowserContextQt::setSpellCheckEnabled(bool enabled) +void ProfileQt::setSpellCheckEnabled(bool enabled) { m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); } -bool BrowserContextQt::isSpellCheckEnabled() const +bool ProfileQt::isSpellCheckEnabled() const { return m_prefService->GetBoolean(spellcheck::prefs::kSpellCheckEnable); } -#endif //ENABLE_SPELLCHECK +#endif // QT_CONFIG(webengine_spellchecker) } // namespace QtWebEngineCore diff --git a/src/core/browser_context_qt.h b/src/core/profile_qt.h index 7fef34df2..00119c053 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/profile_qt.h @@ -37,14 +37,14 @@ ** ****************************************************************************/ -#ifndef BROWSER_CONTEXT_QT_H -#define BROWSER_CONTEXT_QT_H +#ifndef PROFILE_QT_H +#define PROFILE_QT_H #include "chrome/browser/profiles/profile.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "net/url_request/url_request_context.h" - +#include "profile_io_data_qt.h" #include <QtGlobal> QT_BEGIN_NAMESPACE @@ -55,53 +55,54 @@ class PrefService; namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class PermissionManagerQt; class SSLHostStateDelegateQt; -class URLRequestContextGetterQt; -class BrowserContextQt : public Profile +class ProfileQt : public Profile { public: - explicit BrowserContextQt(BrowserContextAdapter *); + explicit ProfileQt(ProfileAdapter *profileAdapter); - virtual ~BrowserContextQt(); + virtual ~ProfileQt(); // BrowserContext implementation: base::FilePath GetPath() const override; bool IsOffTheRecord() const override; net::URLRequestContextGetter *CreateMediaRequestContext() override; - net::URLRequestContextGetter *CreateMediaRequestContextForStoragePartition(const base::FilePath& partition_path, bool in_memory) override; - + net::URLRequestContextGetter *CreateMediaRequestContextForStoragePartition( + const base::FilePath &partition_path, + bool in_memory) override; content::ResourceContext *GetResourceContext() override; content::DownloadManagerDelegate *GetDownloadManagerDelegate() override; - content::BrowserPluginGuestManager* GetGuestManager() override; + content::BrowserPluginGuestManager *GetGuestManager() override; storage::SpecialStoragePolicy *GetSpecialStoragePolicy() override; - content::PushMessagingService* GetPushMessagingService() override; - content::SSLHostStateDelegate* GetSSLHostStateDelegate() override; + content::PushMessagingService *GetPushMessagingService() override; + content::SSLHostStateDelegate *GetSSLHostStateDelegate() override; net::URLRequestContextGetter *CreateRequestContext( content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) override; - net::URLRequestContextGetter* CreateRequestContextForStoragePartition( - const base::FilePath& partition_path, bool in_memory, - content::ProtocolHandlerMap* protocol_handlers, + net::URLRequestContextGetter *CreateRequestContextForStoragePartition( + const base::FilePath &partition_path, bool in_memory, + content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) override; - std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(const base::FilePath& partition_path) override; - content::PermissionManager *GetPermissionManager() override; - content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override; - content::BackgroundSyncController* GetBackgroundSyncController() override; + std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate( + const base::FilePath &partition_path) override; + content::PermissionControllerDelegate * GetPermissionControllerDelegate() override; + content::BackgroundFetchDelegate *GetBackgroundFetchDelegate() override; + content::BackgroundSyncController *GetBackgroundSyncController() override; content::BrowsingDataRemoverDelegate *GetBrowsingDataRemoverDelegate() override; // Profile implementation: - PrefService* GetPrefs() override; - const PrefService* GetPrefs() const override; + PrefService *GetPrefs() override; + const PrefService *GetPrefs() const override; net::URLRequestContextGetter *GetRequestContext() override; - BrowserContextAdapter *adapter() { return m_adapter; } + ProfileAdapter *profileAdapter() { return m_profileAdapter; } -#if BUILDFLAG(ENABLE_SPELLCHECK) - void FailedToLoadDictionary(const std::string& language) override; +#if QT_CONFIG(webengine_spellchecker) + void FailedToLoadDictionary(const std::string &language) override; void setSpellCheckLanguages(const QStringList &languages); QStringList spellCheckLanguages() const; void setSpellCheckEnabled(bool enabled); @@ -111,17 +112,17 @@ public: private: friend class ContentBrowserClientQt; friend class WebContentsAdapter; - std::unique_ptr<content::ResourceContext> resourceContext; - scoped_refptr<URLRequestContextGetterQt> url_request_getter_; - std::unique_ptr<PermissionManagerQt> permissionManager; - std::unique_ptr<SSLHostStateDelegateQt> sslHostStateDelegate; - BrowserContextAdapter *m_adapter; + scoped_refptr<net::URLRequestContextGetter> m_urlRequestContextGetter; + std::unique_ptr<PermissionManagerQt> m_permissionManager; + std::unique_ptr<SSLHostStateDelegateQt> m_sslHostStateDelegate; std::unique_ptr<PrefService> m_prefService; - friend class BrowserContextAdapter; + std::unique_ptr<ProfileIODataQt> m_profileIOData; + ProfileAdapter *m_profileAdapter; + friend class ProfileAdapter; - DISALLOW_COPY_AND_ASSIGN(BrowserContextQt); + DISALLOW_COPY_AND_ASSIGN(ProfileQt); }; } // namespace QtWebEngineCore -#endif // BROWSER_CONTEXT_QT_H +#endif // PROFILE_QT_H diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index 909bbed62..14da1e6cf 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -1,3 +1,4 @@ +import("//build/config/ui.gni") import("//media/media_options.gni") import("//third_party/widevine/cdm/widevine.gni") @@ -13,33 +14,33 @@ include_dirs = [ deps = [ "//base", + "//components/cdm/renderer", "//components/error_page/common", "//components/keyed_service/content", + "//components/network_hints/browser", + "//components/network_hints/common", + "//components/network_hints/renderer", "//components/visitedlink/browser", "//components/visitedlink/renderer", "//components/web_cache/browser", "//components/web_cache/renderer", - "//components/spellcheck:build_features", + "//components/spellcheck:buildflags", "//content/public/app:browser", "//content/public/browser", "//content/public/common", "//content/public/renderer", - "//media:media_features", - "//net:net_browser_services", + "//media:media_buildflags", "//net:net_with_v8", + "//services/proxy_resolver:lib", "//skia", - "//third_party/WebKit/public:blink", - "//ui/accessibility", + "//third_party/blink/public:blink", "//third_party/mesa:mesa_headers", - "//services/proxy_resolver:lib", + "//ui/accessibility", + "//qtwebengine/browser:interfaces", ":qtwebengine_sources", ":qtwebengine_resources" ] -if (enable_widevine) { - deps += [ "//components/cdm/renderer"] -} - if (enable_webrtc) { deps += [ "//third_party/webrtc_overrides" ] } @@ -48,6 +49,12 @@ if (is_linux && !is_desktop_linux) { deps += [ "//ui/events/ozone:events_ozone_evdev"] } +if (use_ozone) { + deps += [ + "//ui/ozone/common" + ] +} + data_deps = [ "//qtwebengine/browser:service_manifests" ] defines = [ diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni index 491b26efc..6e8c3c6eb 100644 --- a/src/core/qtwebengine_resources.gni +++ b/src/core/qtwebengine_resources.gni @@ -16,13 +16,14 @@ group("qtwebengine_resources") { repack("qtwebengine_repack_resources") { sources = [ - "$root_gen_dir/blink/public/resources/blink_resources.pak", "$root_gen_dir/qtwebengine/qt_webengine_resources.pak", "$root_gen_dir/chrome/quota_internals_resources.pak", "$root_gen_dir/chrome/task_scheduler_internals_resources.pak", "$root_gen_dir/components/components_resources.pak", "$root_gen_dir/content/content_resources.pak", + "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak", "$root_gen_dir/net/net_resources.pak", + "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak", "$root_gen_dir/ui/resources/webui_resources.pak", ] output = "$root_out_dir/qtwebengine_resources.pak" @@ -32,44 +33,45 @@ repack("qtwebengine_repack_resources") { "//chrome/browser/resources:task_scheduler_internals_resources", "//components/resources:components_resources_grit", "//content:resources_grit", + "//mojo/public/js:resources", "//net:net_resources_grit", - "//third_party/WebKit/public:resources_grit", + "//third_party/blink/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_scaled_resources_100_percent.pak", + "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak", + "$root_gen_dir/ui/resources/ui_resources_100_percent.pak", ] output = "$root_out_dir/qtwebengine_resources_100p.pak" deps = [ - "//third_party/WebKit/public:scaled_resources_100_percent", "//chrome/renderer:resources_grit", "//components/resources:components_scaled_resources_grit", "//content/app/resources:resources_grit", + "//third_party/blink/public:scaled_resources_100_percent", "//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_scaled_resources_200_percent.pak", + "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_200_percent.pak", + "$root_gen_dir/ui/resources/ui_resources_200_percent.pak", ] output = "$root_out_dir/qtwebengine_resources_200p.pak" deps = [ - "//third_party/WebKit/public:scaled_resources_200_percent", "//chrome/renderer:resources_grit", "//components/resources:components_scaled_resources_grit", "//content/app/resources:resources_grit", + "//third_party/blink/public:scaled_resources_200_percent", "//ui/resources:ui_resources_grd_grit" ] } diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index e0eb3e23a..b1361e727 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -2,10 +2,14 @@ import("//build/config/features.gni") import("//build/config/ui.gni") import("//components/spellcheck/spellcheck_build_features.gni") import("//pdf/features.gni") -import("//ppapi/features/features.gni") -import("//printing/features/features.gni") +import("//ppapi/buildflags/buildflags.gni") +import("//printing/buildflags/buildflags.gni") source_set("qtwebengine_spellcheck_sources") { + include_dirs = core_include_dirs + configs += [ + "//third_party/boringssl:external_config", + ] sources = [ "//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc", "//chrome/browser/spellchecker/spell_check_host_chrome_impl.h", @@ -21,27 +25,26 @@ source_set("qtwebengine_spellcheck_sources") { deps = [ "//components/spellcheck/browser", "//components/spellcheck/renderer", - "//third_party/boringssl", - "//third_party/WebKit/public:blink", + "//third_party/blink/public:blink", "//third_party/hunspell", ] if (is_mac && use_browser_spellchecker) { sources += [ - "//chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc", + "//chrome/browser/spellchecker/spell_check_host_chrome_impl_mac.cc", ] } } source_set("qtwebengine_sources") { - include_dirs = [ - "//skia/config", - "//third_party/boringssl/src/include", - "//third_party/skia/include/core" + configs += [ + "//skia:skia_config", + "//third_party/boringssl:external_config", ] deps = [ - "//chrome/common:features", - "//components/nacl/common:features", - "//extensions/features:features", + "//chrome/common:buildflags", + "//components/nacl/common:buildflags", + "//extensions/buildflags:buildflags", + "//third_party/blink/public/mojom:mojom_platform", ] sources = [ "//chrome/common/custom_handlers/protocol_handler.cc", @@ -123,18 +126,16 @@ source_set("qtwebengine_sources") { "//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", ] deps += [ - "//printing/features:features", + "//printing/buildflags:buildflags", ] } if (enable_pdf) { deps += [ "//pdf", - "//pdf:features", + "//pdf:buildflags", "//components/printing/browser", "//components/printing/renderer", ] diff --git a/src/core/quota_permission_context_qt.cpp b/src/core/quota_permission_context_qt.cpp index f00b2008a..cb1467364 100644 --- a/src/core/quota_permission_context_qt.cpp +++ b/src/core/quota_permission_context_qt.cpp @@ -39,9 +39,9 @@ #include "quota_permission_context_qt.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents.h" #include "quota_request_controller_impl.h" #include "qwebenginequotarequest.h" #include "web_contents_delegate_qt.h" diff --git a/src/core/render_view_context_menu_qt.h b/src/core/render_view_context_menu_qt.h index 1694f66e6..d8ca2775c 100644 --- a/src/core/render_view_context_menu_qt.h +++ b/src/core/render_view_context_menu_qt.h @@ -37,6 +37,17 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef RENDER_VIEW_CONTEXT_MENU_QT_H #define RENDER_VIEW_CONTEXT_MENU_QT_H @@ -44,7 +55,7 @@ namespace QtWebEngineCore { -class QWEBENGINE_EXPORT RenderViewContextMenuQt +class QWEBENGINECORE_PRIVATE_EXPORT RenderViewContextMenuQt { public: enum ContextMenuItem { diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 3641398f6..1582cf733 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -39,47 +39,38 @@ #include "render_widget_host_view_qt.h" -#include "common/qt_messages.h" #include "browser_accessibility_manager_qt.h" -#include "browser_accessibility_qt.h" #include "chromium_overrides.h" -#include "delegated_frame_node.h" +#include "compositor.h" #include "qtwebenginecoreglobal_p.h" #include "render_widget_host_view_qt_delegate.h" #include "type_conversion.h" -#include "web_contents_adapter.h" #include "web_contents_adapter_client.h" #include "web_event_factory.h" -#include "base/command_line.h" -#include "components/viz/service/display/direct_renderer.h" -#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" -#include "content/browser/browser_main_loop.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/cursors/webcursor.h" #include "content/common/input_messages.h" -#include "content/public/browser/browser_accessibility_state.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/common/content_switches.h" #include "third_party/skia/include/core/SkColor.h" -#include "third_party/WebKit/public/platform/WebColor.h" -#include "third_party/WebKit/public/platform/WebCursorInfo.h" -#include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/base/resource/resource_bundle.h" +#include "third_party/blink/public/platform/web_cursor_info.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_provider_config_helper.h" #include "ui/events/gesture_detection/motion_event.h" -#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/image/image_skia.h" + +#if defined(USE_OZONE) +#include "ui/base/clipboard/scoped_clipboard_writer.h" +#endif #if defined(USE_AURA) #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursors_aura.h" +#include "ui/base/resource/resource_bundle.h" #endif #include <private/qguiapplication_p.h> @@ -99,9 +90,7 @@ #include <QVariant> #include <QWheelEvent> #include <QWindow> -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) #include <QtGui/private/qinputcontrol_p.h> -#endif #include <QtGui/qaccessible.h> namespace QtWebEngineCore { @@ -117,14 +106,10 @@ enum ImStateFlags { static inline ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { ui::LatencyInfo latency_info; // The latency number should only be added if the timestamp is valid. - if (event.TimeStampSeconds()) { - const int64_t time_micros = static_cast<int64_t>( - event.TimeStampSeconds() * base::Time::kMicrosecondsPerSecond); + if (!event.TimeStamp().is_null()) { latency_info.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, - 0, - 0, - base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros), + event.TimeStamp(), 1); } return latency_info; @@ -191,55 +176,7 @@ static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs, const static inline bool isCommonTextEditShortcut(const QKeyEvent *ke) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) return QInputControl::isCommonTextEditShortcut(ke); -#else - if (ke->modifiers() == Qt::NoModifier - || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - return true; - } else { - switch (ke->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - return true; - default: - break; - } - } - } else if (ke->matches(QKeySequence::Copy) - || ke->matches(QKeySequence::Paste) - || ke->matches(QKeySequence::Cut) - || ke->matches(QKeySequence::Redo) - || ke->matches(QKeySequence::Undo) - || ke->matches(QKeySequence::MoveToNextWord) - || ke->matches(QKeySequence::MoveToPreviousWord) - || ke->matches(QKeySequence::MoveToStartOfDocument) - || ke->matches(QKeySequence::MoveToEndOfDocument) - || ke->matches(QKeySequence::SelectNextWord) - || ke->matches(QKeySequence::SelectPreviousWord) - || ke->matches(QKeySequence::SelectStartOfLine) - || ke->matches(QKeySequence::SelectEndOfLine) - || ke->matches(QKeySequence::SelectStartOfBlock) - || ke->matches(QKeySequence::SelectEndOfBlock) - || ke->matches(QKeySequence::SelectStartOfDocument) - || ke->matches(QKeySequence::SelectEndOfDocument) - || ke->matches(QKeySequence::SelectAll) - ) { - return true; - } - return false; -#endif } static uint32_t s_eventId = 0; @@ -255,7 +192,7 @@ public: , dpiScale(dpiScale) { // ACTION_DOWN and ACTION_UP must be accesssed through pointer_index 0 - Q_ASSERT((action != ACTION_DOWN && action != ACTION_UP) || index == 0); + Q_ASSERT((action != Action::DOWN && action != Action::UP) || index == 0); } uint32_t GetUniqueEventId() const override { return eventId; } @@ -292,7 +229,7 @@ public: float GetHistoricalTouchMajor(size_t pointer_index, size_t historical_index) const override { return 0; } float GetHistoricalX(size_t pointer_index, size_t historical_index) const override { return 0; } float GetHistoricalY(size_t pointer_index, size_t historical_index) const override { return 0; } - ToolType GetToolType(size_t pointer_index) const override { return ui::MotionEvent::TOOL_TYPE_FINGER; } + ToolType GetToolType(size_t pointer_index) const override { return ui::MotionEvent::ToolType::FINGER; } int GetButtonState() const override { return 0; } private: @@ -319,34 +256,25 @@ bool isAccessibilityEnabled() { } RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) - : m_host(content::RenderWidgetHostImpl::From(widget)) + : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) , m_gestureProvider(QtGestureProviderConfig(), this) , m_sendMotionActionDown(false) , m_touchMotionStarted(false) - , m_chromiumCompositorData(new ChromiumCompositorData) - , m_needsDelegatedFrameAck(false) + , m_compositor(new Compositor) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) - , m_rendererCompositorFrameSink(0) , m_imeInProgress(false) , m_receivedEmptyImeEvent(false) - , m_initPending(false) - , m_beginFrameSource(nullptr) - , m_needsBeginFrames(false) - , m_addedFrameObserver(false) - , m_backgroundColor(SK_ColorWHITE) , m_imState(0) , m_anchorPositionWithinSelection(-1) , m_cursorPositionWithinSelection(-1) , m_cursorPosition(0) , m_emptyPreviousSelection(true) , m_wheelAckPending(false) + , m_pendingResize(false) + , m_mouseWheelPhaseHandler(this) { - auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); - m_beginFrameSource.reset(new viz::DelayBasedBeginFrameSource( - base::MakeUnique<viz::DelayBasedTimeSource>(task_runner), 0)); - - m_host->SetView(this); + host()->SetView(this); #ifndef QT_NO_ACCESSIBILITY if (isAccessibilityEnabled()) { QAccessible::installActivationObserver(this); @@ -360,6 +288,8 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability); + + m_localSurfaceId = m_localSurfaceIdAllocator.GenerateId(); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() @@ -376,6 +306,7 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) { m_delegate.reset(delegate); + m_compositor->setViewDelegate(delegate); } void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterClient) @@ -387,18 +318,10 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC m_adapterClientDestroyedConnection = QObject::connect(adapterClient->holdingQObject(), &QObject::destroyed, [this] { m_adapterClient = nullptr; }); - if (m_initPending) - InitAsChild(0); } void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) { - if (!m_adapterClient) { - m_initPending = true; - return; - } - m_initPending = false; - m_delegate->initAsChild(m_adapterClient); } void RenderWidgetHostViewQt::InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect& rect) @@ -410,11 +333,6 @@ void RenderWidgetHostViewQt::InitAsFullscreen(content::RenderWidgetHostView*) { } -content::RenderWidgetHostImpl* RenderWidgetHostViewQt::GetRenderWidgetHostImpl() const -{ - return m_host; -} - void RenderWidgetHostViewQt::SetSize(const gfx::Size& size) { int width = size.width(); @@ -431,11 +349,7 @@ void RenderWidgetHostViewQt::SetBounds(const gfx::Rect& screenRect) SetSize(screenRect.size()); } -gfx::Vector2dF RenderWidgetHostViewQt::GetLastScrollOffset() const { - return m_lastScrollOffset; -} - -gfx::Size RenderWidgetHostViewQt::GetPhysicalBackingSize() const +gfx::Size RenderWidgetHostViewQt::GetCompositorViewportPixelSize() const { if (!m_delegate || !m_delegate->window() || !m_delegate->window()->screen()) return gfx::Size(); @@ -479,7 +393,7 @@ void RenderWidgetHostViewQt::Focus() { if (!IsPopup()) m_delegate->setKeyboardFocus(); - m_host->Focus(); + host()->Focus(); } bool RenderWidgetHostViewQt::HasFocus() const @@ -517,27 +431,17 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const return gfx::BoundingRect(p1, p2); } -SkColor RenderWidgetHostViewQt::background_color() const -{ - return m_backgroundColor; -} - -void RenderWidgetHostViewQt::SetBackgroundColor(SkColor color) +void RenderWidgetHostViewQt::UpdateBackgroundColor() { - if (m_backgroundColor == color) - return; - m_backgroundColor = color; - // Set the background of the compositor if necessary - m_delegate->setClearColor(toQt(color)); - // Set the background of the blink::FrameView - m_host->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE); - m_host->Send(new RenderViewObserverQt_SetBackgroundColor(m_host->GetRoutingID(), color)); + auto color = GetBackgroundColor(); + if (color) { + m_delegate->setClearColor(toQt(*color)); + } } // Return value indicates whether the mouse is locked successfully or not. bool RenderWidgetHostViewQt::LockMouse() { - mouse_locked_ = true; m_previousMousePosition = QCursor::pos(); m_delegate->lockMouse(); qApp->setOverrideCursor(Qt::BlankCursor); @@ -546,14 +450,18 @@ bool RenderWidgetHostViewQt::LockMouse() void RenderWidgetHostViewQt::UnlockMouse() { - mouse_locked_ = false; m_delegate->unlockMouse(); qApp->restoreOverrideCursor(); - m_host->LostMouseLock(); + host()->LostMouseLock(); } void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) { + DisplayCursor(webCursor); +} + +void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) +{ content::CursorInfo cursorInfo; webCursor.GetCursorInfo(&cursorInfo); Qt::CursorShape shape = Qt::ArrowCursor; @@ -620,6 +528,12 @@ void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) case blink::WebCursorInfo::kTypeProgress: shape = Qt::BusyCursor; break; + case blink::WebCursorInfo::kTypeCopy: + shape = Qt::DragCopyCursor; + break; + case blink::WebCursorInfo::kTypeAlias: + shape = Qt::DragLinkCursor; + break; #if defined(USE_AURA) case blink::WebCursorInfo::kTypeVerticalText: auraType = ui::CursorType::kVerticalText; @@ -630,12 +544,6 @@ void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) case blink::WebCursorInfo::kTypeContextMenu: auraType = ui::CursorType::kContextMenu; break; - case blink::WebCursorInfo::kTypeAlias: - auraType = ui::CursorType::kAlias; - break; - case blink::WebCursorInfo::kTypeCopy: - auraType = ui::CursorType::kCopy; - break; case blink::WebCursorInfo::kTypeZoomIn: auraType = ui::CursorType::kZoomIn; break; @@ -646,8 +554,6 @@ void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) case blink::WebCursorInfo::kTypeVerticalText: case blink::WebCursorInfo::kTypeCell: case blink::WebCursorInfo::kTypeContextMenu: - case blink::WebCursorInfo::kTypeAlias: - case blink::WebCursorInfo::kTypeCopy: case blink::WebCursorInfo::kTypeZoomIn: case blink::WebCursorInfo::kTypeZoomOut: // FIXME: Support on OS X @@ -740,40 +646,26 @@ void RenderWidgetHostViewQt::Destroy() void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) { - if (m_adapterClient) - m_adapterClient->setToolTip(toQt(tooltip_text)); + DisplayTooltipText(tooltip_text); } -bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) +void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_text) { - return false; + if (m_adapterClient) + m_adapterClient->setToolTip(toQt(tooltip_text)); } void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSink) { - // Accumulated resources belong to the old RendererCompositorFrameSink and - // should not be returned. - m_resourcesToRelease.clear(); - m_rendererCompositorFrameSink = frameSink; + m_compositor->setFrameSinkClient(frameSink); } -void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, viz::mojom::HitTestRegionListPtr) +void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList>) { bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset); bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.root_layer_size); m_lastScrollOffset = frame.metadata.root_scroll_offset; m_lastContentsSize = frame.metadata.root_layer_size; - m_backgroundColor = frame.metadata.root_background_color; - if (m_localSurfaceId != local_surface_id) { - m_localSurfaceId = local_surface_id; - // FIXME: update frame_size and device_scale_factor? - // FIXME: showPrimarySurface()? - } - Q_ASSERT(!m_needsDelegatedFrameAck); - m_needsDelegatedFrameAck = true; - m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); - m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor; - m_chromiumCompositorData->frameData = std::move(frame); // Force to process swap messages uint32_t frame_token = frame.metadata.frame_token; @@ -783,9 +675,9 @@ void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &lo // Support experimental.viewport.devicePixelRatio, see GetScreenInfo implementation below. float dpiScale = this->dpiScale(); if (dpiScale != 0 && dpiScale != 1) - m_chromiumCompositorData->frameDevicePixelRatio /= dpiScale; + frame.metadata.device_scale_factor /= dpiScale; - m_delegate->update(); + m_compositor->submitFrame(std::move(frame)); if (m_loadVisuallyCommittedState == NotCommitted) { m_loadVisuallyCommittedState = DidFirstCompositorFrameSwap; @@ -800,9 +692,9 @@ void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &lo m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } -void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo* results) +void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo *results) const { - QWindow* window = m_delegate->window(); + QWindow *window = m_delegate->window(); if (!window) return; GetScreenInfoFromNativeWindow(window, results); @@ -886,13 +778,13 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t if (!selection) return; -#if defined(USE_X11) +#if defined(USE_OZONE) if (!selection->selected_text().empty() && selection->user_initiated()) { // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION); clipboard_writer.WriteText(selection->selected_text()); } -#endif // defined(USE_X11) +#endif // defined(USE_OZONE) m_imState |= ImStateFlags::TextSelectionUpdated; if (m_imState == ImStateFlags::AllFlags @@ -972,60 +864,72 @@ void RenderWidgetHostViewQt::selectionChanged() void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) { - m_host->ForwardGestureEvent(ui::CreateWebGestureEventFromGestureEventData(gesture)); + host()->ForwardGestureEvent(ui::CreateWebGestureEventFromGestureEventData(gesture)); } -QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) +viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) { - DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode); - if (!frameNode) - frameNode = new DelegatedFrameNode; + base::OnceCallback<void()> allocation_task = + base::BindOnce(&RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete, + base::Unretained(this), metadata); + return viz::ScopedSurfaceIdAllocator(std::move(allocation_task)); +} - frameNode->commit(m_chromiumCompositorData.data(), &m_resourcesToRelease, m_delegate.get()); +void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata) +{ + if (metadata.local_surface_id) + m_localSurfaceIdAllocator.UpdateFromChild(*metadata.local_surface_id); - // This is possibly called from the Qt render thread, post the ack back to the UI - // to tell the child compositors to release resources and trigger a new frame. - if (m_needsDelegatedFrameAck) { - m_needsDelegatedFrameAck = false; - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, - base::Bind(&RenderWidgetHostViewQt::sendDelegatedFrameAck, AsWeakPtr())); + m_localSurfaceId = m_localSurfaceIdAllocator.GenerateId(); + host()->SendScreenRects(); + if (m_pendingResize) { + if (host()->SynchronizeVisualProperties()) + m_pendingResize = false; } +} - return frameNode; +QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) +{ + if (m_pendingResize && host()) { + if (host()->SynchronizeVisualProperties()) + m_pendingResize = false; + } + return m_compositor->updatePaintNode(oldNode); } void RenderWidgetHostViewQt::notifyResize() { - m_host->WasResized(); - m_host->SendScreenRects(); + m_pendingResize = true; + if (host()->SynchronizeVisualProperties()) + m_pendingResize = false; } void RenderWidgetHostViewQt::notifyShown() { - m_host->WasShown(ui::LatencyInfo()); + host()->WasShown(false); } void RenderWidgetHostViewQt::notifyHidden() { - m_host->WasHidden(); + host()->WasHidden(); } void RenderWidgetHostViewQt::windowBoundsChanged() { - m_host->SendScreenRects(); - if (m_delegate->window()) - m_host->NotifyScreenInfoChanged(); + host()->SendScreenRects(); + if (m_delegate && m_delegate->window()) + host()->NotifyScreenInfoChanged(); } void RenderWidgetHostViewQt::windowChanged() { - if (m_delegate->window()) - m_host->NotifyScreenInfoChanged(); + if (m_delegate && m_delegate->window()) + host()->NotifyScreenInfoChanged(); } bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) { - Q_ASSERT(m_host->GetView()); + Q_ASSERT(host()->GetView()); switch (event->type()) { case QEvent::ShortcutOverride: { @@ -1067,7 +971,8 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) return false; } case QEvent::MouseButtonPress: - Focus(); // Fall through. + Focus(); + Q_FALLTHROUGH(); case QEvent::MouseButtonRelease: case QEvent::MouseMove: // Skip second MouseMove event when a window is being adopted, so that Chromium @@ -1088,7 +993,8 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) handleWheelEvent(static_cast<QWheelEvent*>(event)); break; case QEvent::TouchBegin: - Focus(); // Fall through. + Focus(); + Q_FALLTHROUGH(); case QEvent::TouchUpdate: case QEvent::TouchEnd: case QEvent::TouchCancel: @@ -1096,7 +1002,8 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) break; #if QT_CONFIG(tabletevent) case QEvent::TabletPress: - Focus(); // Fall through. + Focus(); + Q_FALLTHROUGH(); case QEvent::TabletRelease: case QEvent::TabletMove: handleTabletEvent(static_cast<QTabletEvent*>(event)); @@ -1122,7 +1029,7 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) break; case QEvent::HoverLeave: case QEvent::Leave: - m_host->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); + host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event)); break; default: return false; @@ -1149,10 +1056,12 @@ QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) case Qt::ImCursorRectangle: { if (text_input_manager_) { if (auto *region = text_input_manager_->GetSelectionRegion()) { - gfx::Rect caretRect = gfx::RectBetweenSelectionBounds(region->anchor, region->focus); - if (caretRect.width() == 0) - caretRect.set_width(1); // IME API on Windows expects a width > 0 - return toQt(caretRect); + if (region->focus.GetHeight() > 0) { + gfx::Rect caretRect = gfx::RectBetweenSelectionBounds(region->anchor, region->focus); + if (caretRect.width() == 0) + caretRect.set_width(1); // IME API on Windows expects a width > 0 + return toQt(caretRect); + } } } return QVariant(); @@ -1180,8 +1089,8 @@ void RenderWidgetHostViewQt::closePopup() // We notify the popup to be closed by telling it that it lost focus. WebKit does the rest // (hiding the widget and automatic memory cleanup via // RenderWidget::CloseWidgetSoon() -> RenderWidgetHostImpl::ShutdownAndDestroyWidget(true). - m_host->SetActive(false); - m_host->Blur(); + host()->SetActive(false); + host()->Blur(); } void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { @@ -1190,15 +1099,6 @@ void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWit m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, /*fixme: ?? */false); } -void RenderWidgetHostViewQt::sendDelegatedFrameAck() -{ - m_beginFrameSource->DidFinishFrame(this); - std::vector<viz::ReturnedResource> resources; - m_resourcesToRelease.swap(resources); - if (m_rendererCompositorFrameSink) - m_rendererCompositorFrameSink->DidReceiveCompositorFrameAck(resources); -} - void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) { auto result = m_gestureProvider.OnTouchEvent(motionEvent); @@ -1206,8 +1106,9 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve return; blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, - result.moved_beyond_slop_region); - m_host->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); + result.moved_beyond_slop_region, + false /*hovering, FIXME ?*/); + host()->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); } QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints) @@ -1260,11 +1161,11 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) // We're getting the composition result in a key event. if (ev->key() != 0) { // The key event is not a result of an IME composition. Cancel IME. - m_host->ImeCancelComposition(); + host()->ImeCancelComposition(); m_receivedEmptyImeEvent = false; } else { if (ev->type() == QEvent::KeyRelease) { - m_host->ImeCommitText(toString16(ev->text()), + host()->ImeCommitText(toString16(ev->text()), std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0); @@ -1282,13 +1183,13 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) content::EditCommands commands; commands.emplace_back(m_editCommand, ""); m_editCommand.clear(); - m_host->ForwardKeyboardEventWithCommands(webEvent, latency, &commands, nullptr); + host()->ForwardKeyboardEventWithCommands(webEvent, latency, &commands, nullptr); return; } bool keyDownTextInsertion = webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && webEvent.text[0]; webEvent.skip_in_browser = keyDownTextInsertion; - m_host->ForwardKeyboardEvent(webEvent); + host()->ForwardKeyboardEvent(webEvent); if (keyDownTextInsertion) { // Blink won't consume the RawKeyDown, but rather the Char event in this case. @@ -1296,7 +1197,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) // The same os_event will be set on both NativeWebKeyboardEvents. webEvent.skip_in_browser = false; webEvent.SetType(blink::WebInputEvent::kChar); - m_host->ForwardKeyboardEvent(webEvent); + host()->ForwardKeyboardEvent(webEvent); } } @@ -1305,7 +1206,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) // Reset input manager state m_imState = 0; - if (!m_host) + if (!host()) return; QString commitString = ev->commitString(); @@ -1334,13 +1235,12 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) end = qMax(0, start + end); } - QTextCharFormat format = qvariant_cast<QTextFormat>(attribute.value).toCharFormat(); + underlines.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, start, end, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT)); - QColor underlineColor(0, 0, 0, 0); + QTextCharFormat format = qvariant_cast<QTextFormat>(attribute.value).toCharFormat(); if (format.underlineStyle() != QTextCharFormat::NoUnderline) - underlineColor = format.underlineColor(); + underlines.back().underline_color = toSk(format.underlineColor()); - underlines.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, start, end, toSk(underlineColor), /*thick*/ false, SK_ColorTRANSPARENT)); break; } case QInputMethodEvent::Cursor: @@ -1419,7 +1319,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) m_receivedEmptyImeEvent = false; if (m_imeInProgress) { m_imeInProgress = false; - m_host->ImeCancelComposition(); + host()->ImeCancelComposition(); } } @@ -1430,7 +1330,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) // Finish compostion: insert or erase text. if (!commitString.isEmpty() || replacementLength > 0) { - m_host->ImeCommitText(toString16(commitString), + host()->ImeCommitText(toString16(commitString), underlines, replacementRange, 0); @@ -1441,7 +1341,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) // Be aware of that, we might get a commit string and a pre-edit string in a single event and // this means a new composition. if (!preeditString.isEmpty()) { - m_host->ImeSetComposition(toString16(preeditString), + host()->ImeSetComposition(toString16(preeditString), underlines, replacementRange, selectionRange.start(), @@ -1477,8 +1377,10 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) { if (!m_wheelAckPending) { Q_ASSERT(m_pendingWheelEvents.isEmpty()); - m_wheelAckPending = true; - m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale())); + blink::WebMouseWheelEvent webEvent = WebEventFactory::toWebWheelEvent(ev, dpiScale()); + m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); + host()->ForwardWheelEvent(webEvent); return; } if (!m_pendingWheelEvents.isEmpty()) { @@ -1489,16 +1391,26 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) m_pendingWheelEvents.append(WebEventFactory::toWebWheelEvent(ev, dpiScale())); } -void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &/*event*/, content::InputEventAckState /*ack_result*/) +void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState /*ack_result*/) { + if (event.phase == blink::WebMouseWheelEvent::kPhaseEnded) + return; + Q_ASSERT(m_wheelAckPending); m_wheelAckPending = false; - if (!m_pendingWheelEvents.isEmpty()) { - m_wheelAckPending = true; - m_host->ForwardWheelEvent(m_pendingWheelEvents.takeFirst()); + while (!m_pendingWheelEvents.isEmpty() && !m_wheelAckPending) { + blink::WebMouseWheelEvent webEvent = m_pendingWheelEvents.takeFirst(); + m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); + host()->ForwardWheelEvent(webEvent); } // TODO: We could forward unhandled wheelevents to our parent. } +content::MouseWheelPhaseHandler *RenderWidgetHostViewQt::GetMouseWheelPhaseHandler() +{ + return &m_mouseWheelPhaseHandler; +} + void RenderWidgetHostViewQt::clearPreviousTouchMotionState() { m_previousTouchPoints.clear(); @@ -1511,7 +1423,7 @@ void RenderWidgetHostViewQt::handleGestureEvent(QNativeGestureEvent *ev) const Qt::NativeGestureType type = ev->gestureType(); // These are the only supported gestures by Chromium so far. if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) { - m_host->ForwardGestureEvent(WebEventFactory::toWebGestureEvent( + host()->ForwardGestureEvent(WebEventFactory::toWebGestureEvent( ev, static_cast<double>(dpiScale()))); } @@ -1569,7 +1481,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) if (touchPoints.isEmpty()) touchPoints = m_previousTouchPoints; clearPreviousTouchMotionState(); - MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL, + MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, ev->modifiers(), dpiScale()); processMotionEvent(cancelEvent); return; @@ -1604,18 +1516,18 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) switch (touchPoints[i].state()) { case Qt::TouchPointPressed: if (m_sendMotionActionDown) { - action = ui::MotionEvent::ACTION_DOWN; + action = ui::MotionEvent::Action::DOWN; m_sendMotionActionDown = false; } else { - action = ui::MotionEvent::ACTION_POINTER_DOWN; + action = ui::MotionEvent::Action::POINTER_DOWN; } break; case Qt::TouchPointMoved: - action = ui::MotionEvent::ACTION_MOVE; + action = ui::MotionEvent::Action::MOVE; break; case Qt::TouchPointReleased: - action = touchPoints.size() > 1 ? ui::MotionEvent::ACTION_POINTER_UP : - ui::MotionEvent::ACTION_UP; + action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP : + ui::MotionEvent::Action::UP; break; default: // Ignore Qt::TouchPointStationary @@ -1681,20 +1593,20 @@ void RenderWidgetHostViewQt::handlePointerEvent(T *event) #endif } - m_host->ForwardMouseEvent(webEvent); + host()->ForwardMouseEvent(webEvent); } void RenderWidgetHostViewQt::handleHoverEvent(QHoverEvent *ev) { - m_host->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev, dpiScale())); + host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev, dpiScale())); } void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) { if (ev->gotFocus()) { - m_host->GotFocus(); - m_host->SetActive(true); - content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(m_host); + host()->GotFocus(); + host()->SetActive(true); + content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(host()); Q_ASSERT(viewHost); if (ev->reason() == Qt::TabFocusReason) viewHost->SetInitialFocus(false); @@ -1702,52 +1614,20 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) viewHost->SetInitialFocus(true); ev->accept(); } else if (ev->lostFocus()) { - m_host->SetActive(false); - m_host->Blur(); + host()->SetActive(false); + host()->Blur(); ev->accept(); } } void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames) { - m_needsBeginFrames = needs_begin_frames; - updateNeedsBeginFramesInternal(); -} - -void RenderWidgetHostViewQt::updateNeedsBeginFramesInternal() -{ - Q_ASSERT(m_beginFrameSource); - - if (m_addedFrameObserver == m_needsBeginFrames) - return; - - if (m_needsBeginFrames) - m_beginFrameSource->AddObserver(this); - else - m_beginFrameSource->RemoveObserver(this); - m_addedFrameObserver = m_needsBeginFrames; -} - -bool RenderWidgetHostViewQt::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) -{ - m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval); - if (m_rendererCompositorFrameSink) - m_rendererCompositorFrameSink->OnBeginFrame(args); - else // FIXME: is this else part ever needed? - m_host->Send(new ViewMsg_BeginFrame(m_host->GetRoutingID(), args)); - return true; -} - -void RenderWidgetHostViewQt::OnBeginFrameSourcePausedChanged(bool paused) -{ - // Ignored for now. If the begin frame source is paused, the renderer - // doesn't need to be informed about it and will just not receive more - // begin frames. + m_compositor->setNeedsBeginFrames(needs_begin_frames); } content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost() { - content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(m_host); + content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(host()); if (!viewHost) return nullptr; @@ -1775,4 +1655,35 @@ viz::SurfaceId RenderWidgetHostViewQt::GetCurrentSurfaceId() const return viz::SurfaceId(); } +const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const +{ + return viz::FrameSinkIdAllocator::InvalidFrameSinkId(); +} + +const viz::LocalSurfaceId &RenderWidgetHostViewQt::GetLocalSurfaceId() const +{ + return m_localSurfaceId; +} + +void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) +{ + DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); + DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewGuest()); + base::Optional<SkColor> color = view->GetBackgroundColor(); + if (color) + SetBackgroundColor(*color); +} + +void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForLayoutTest() +{ + ++m_latestCaptureSequenceNumber; + if (host()) + host()->SynchronizeVisualProperties(); +} + +uint32_t RenderWidgetHostViewQt::GetCaptureSequenceNumber() const +{ + return m_latestCaptureSequenceNumber; +} + } // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index cc62fa110..6a1134ac0 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -45,7 +45,9 @@ #include "base/memory/weak_ptr.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/resources/transferable_resource.h" +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/browser/accessibility/browser_accessibility_manager.h" +#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/renderer_host/text_input_manager.h" #include "content/common/view_messages.h" @@ -58,21 +60,10 @@ #include <QtGui/qaccessible.h> #include <QtGui/QTouchEvent> -#include "delegated_frame_node.h" - QT_BEGIN_NAMESPACE -class QEvent; -class QFocusEvent; -class QHoverEvent; -class QKeyEvent; -class QMouseEvent; -class QVariant; -class QWheelEvent; class QAccessibleInterface; QT_END_NAMESPACE -class WebContentsAdapterClient; - namespace content { class RenderFrameHost; class RenderWidgetHostImpl; @@ -80,6 +71,8 @@ class RenderWidgetHostImpl; namespace QtWebEngineCore { +class Compositor; + struct MultipleMouseClickHelper { QPoint lastPressPosition; @@ -101,7 +94,6 @@ class RenderWidgetHostViewQt , public ui::GestureProviderClient , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> - , public viz::BeginFrameObserverBase #ifndef QT_NO_ACCESSIBILITY , public QAccessible::ActivationObserver #endif // QT_NO_ACCESSIBILITY @@ -124,11 +116,9 @@ public: void InitAsChild(gfx::NativeView) override; void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) override; void InitAsFullscreen(content::RenderWidgetHostView*) override; - content::RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override; void SetSize(const gfx::Size& size) override; void SetBounds(const gfx::Rect&) override; - gfx::Vector2dF GetLastScrollOffset() const override; - gfx::Size GetPhysicalBackingSize() const override; + gfx::Size GetCompositorViewportPixelSize() const override; gfx::NativeView GetNativeView() const override; gfx::NativeViewAccessible GetNativeViewAccessible() override; void Focus() override; @@ -138,29 +128,37 @@ public: void Hide() override; bool IsShowing() override; gfx::Rect GetViewBounds() const override; - SkColor background_color() const override; - void SetBackgroundColor(SkColor color) override; + void UpdateBackgroundColor() override; bool LockMouse() override; void UnlockMouse() override; void UpdateCursor(const content::WebCursor&) override; + void DisplayCursor(const content::WebCursor&) override; void SetIsLoading(bool) override; void ImeCancelComposition() override; void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) override; void RenderProcessGone(base::TerminationStatus, int) override; void Destroy() override; void SetTooltipText(const base::string16 &tooltip_text) override; - bool HasAcceleratedSurface(const gfx::Size&) override; + void DisplayTooltipText(const base::string16& tooltip_text) override; void DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; - void SubmitCompositorFrame(const viz::LocalSurfaceId&, viz::CompositorFrame, viz::mojom::HitTestRegionListPtr) override; + void SubmitCompositorFrame(const viz::LocalSurfaceId&, viz::CompositorFrame, base::Optional<viz::HitTestRegionList>) override; void WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState ack_result) override; + content::MouseWheelPhaseHandler *GetMouseWheelPhaseHandler() override; + viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override; + void OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata); - void GetScreenInfo(content::ScreenInfo* results); + void GetScreenInfo(content::ScreenInfo* results) const override; gfx::Rect GetBoundsInRootWindow() override; void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) override; void ClearCompositorFrame() override; void SetNeedsBeginFrames(bool needs_begin_frames) override; void SetWantsAnimateOnlyBeginFrames() override; viz::SurfaceId GetCurrentSurfaceId() const override; + const viz::FrameSinkId &GetFrameSinkId() const override; + const viz::LocalSurfaceId &GetLocalSurfaceId() const override; + void TakeFallbackContentFrom(content::RenderWidgetHostView *view) override; + void EnsureSurfaceSynchronizedForLayoutTest() override; + uint32_t GetCaptureSequenceNumber() const override; // Overridden from ui::GestureProviderClient. void OnGestureEvent(const ui::GestureEventData& gesture) override; @@ -181,10 +179,6 @@ public: void OnSelectionBoundsChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view) override; void OnTextSelectionChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view) override; - // cc::BeginFrameObserverBase implementation. - bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) override; - void OnBeginFrameSourcePausedChanged(bool paused) override; - void handleMouseEvent(QMouseEvent*); void handleKeyEvent(QKeyEvent*); void handleWheelEvent(QWheelEvent*); @@ -204,10 +198,7 @@ public: #if defined(OS_MACOSX) void SetActive(bool active) override { QT_NOT_YET_IMPLEMENTED } - bool IsSpeaking() const override { QT_NOT_YET_IMPLEMENTED; return false; } void SpeakSelection() override { QT_NOT_YET_IMPLEMENTED } - void StopSpeaking() override { QT_NOT_YET_IMPLEMENTED } - bool SupportsSpeech() const override { QT_NOT_YET_IMPLEMENTED; return false; } void ShowDefinitionForSelection() override { QT_NOT_YET_IMPLEMENTED } #endif // defined(OS_MACOSX) @@ -221,9 +212,9 @@ public: void setLoadVisuallyCommittedState(LoadVisuallyCommittedState state) { m_loadVisuallyCommittedState = state; } gfx::SizeF lastContentsSize() const { return m_lastContentsSize; } + gfx::Vector2dF lastScrollOffset() const { return m_lastScrollOffset; } private: - void sendDelegatedFrameAck(); void processMotionEvent(const ui::MotionEvent &motionEvent); void clearPreviousTouchMotionState(); QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints); @@ -236,7 +227,6 @@ private: content::RenderFrameHost *getFocusedFrameHost(); ui::TextInputType getTextInputType() const; - content::RenderWidgetHostImpl *m_host; ui::FilteredGestureProvider m_gestureProvider; base::TimeDelta m_eventsToNowDelta; bool m_sendMotionActionDown; @@ -245,30 +235,21 @@ private: QList<QTouchEvent::TouchPoint> m_previousTouchPoints; std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; - QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; - std::vector<viz::ReturnedResource> m_resourcesToRelease; - bool m_needsDelegatedFrameAck; + std::unique_ptr<Compositor> m_compositor; LoadVisuallyCommittedState m_loadVisuallyCommittedState; QMetaObject::Connection m_adapterClientDestroyedConnection; WebContentsAdapterClient *m_adapterClient; MultipleMouseClickHelper m_clickHelper; - viz::mojom::CompositorFrameSinkClient *m_rendererCompositorFrameSink; bool m_imeInProgress; bool m_receivedEmptyImeEvent; QPoint m_previousMousePosition; - bool m_initPending; - - std::unique_ptr<viz::SyntheticBeginFrameSource> m_beginFrameSource; - bool m_needsBeginFrames; - bool m_addedFrameObserver; - gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; - SkColor m_backgroundColor; viz::LocalSurfaceId m_localSurfaceId; + viz::ParentLocalSurfaceIdAllocator m_localSurfaceIdAllocator; uint m_imState; int m_anchorPositionWithinSelection; @@ -280,8 +261,11 @@ private: bool m_imeHasHiddenTextCapability; bool m_wheelAckPending; + bool m_pendingResize; QList<blink::WebMouseWheelEvent> m_pendingWheelEvents; + content::MouseWheelPhaseHandler m_mouseWheelPhaseHandler; + uint32_t m_latestCaptureSequenceNumber = 0u; std::string m_editCommand; }; diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index 3ac3ccc1e..991c26ea8 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -37,29 +37,36 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H #define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QRect> #include <QtGui/qwindowdefs.h> QT_BEGIN_NAMESPACE -class QCursor; class QEvent; -class QPainter; class QSGLayer; class QSGNode; class QSGRectangleNode; class QSGTexture; class QVariant; -class QWindow; class QInputMethodEvent; class QSGInternalImageNode; class QSGImageNode; -typedef QSGImageNode QSGTextureNode; QT_END_NAMESPACE @@ -67,7 +74,7 @@ namespace QtWebEngineCore { class WebContentsAdapterClient; -class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegateClient { +class QWEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegateClient { public: virtual ~RenderWidgetHostViewQtDelegateClient() { } virtual QSGNode *updatePaintNode(QSGNode *) = 0; @@ -81,10 +88,9 @@ public: virtual void closePopup() = 0; }; -class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegate { +class QWEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegate { public: virtual ~RenderWidgetHostViewQtDelegate() { } - virtual void initAsChild(WebContentsAdapterClient*) = 0; virtual void initAsPopup(const QRect&) = 0; virtual QRectF screenRect() const = 0; virtual QRectF contentsRect() const = 0; @@ -98,8 +104,8 @@ public: virtual QWindow* window() const = 0; virtual QSGTexture *createTextureFromImage(const QImage &) = 0; virtual QSGLayer *createLayer() = 0; - virtual QSGInternalImageNode *createImageNode() = 0; - virtual QSGTextureNode *createTextureNode() = 0; + virtual QSGInternalImageNode *createInternalImageNode() = 0; + virtual QSGImageNode *createImageNode() = 0; virtual QSGRectangleNode *createRectangleNode() = 0; virtual void update() = 0; virtual void updateCursor(const QCursor &) = 0; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index db3ab5745..3eda3993a 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -40,21 +40,21 @@ #include "renderer/content_renderer_client_qt.h" #include "common/qt_messages.h" -#include "printing/features/features.h" #include "renderer/content_settings_observer_qt.h" - #include "base/strings/string_split.h" -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) #include "components/spellcheck/renderer/spellcheck.h" #include "components/spellcheck/renderer/spellcheck_provider.h" #endif +#include "components/cdm/renderer/external_clear_key_key_system_properties.h" #include "components/cdm/renderer/widevine_key_system_properties.h" #include "components/error_page/common/error.h" #include "components/error_page/common/error_page_params.h" #include "components/error_page/common/localized_error.h" -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#include "components/network_hints/renderer/prescient_networking_dispatcher.h" +#if QT_CONFIG(webengine_printing_and_pdf) #include "components/printing/renderer/print_render_frame_helper.h" -#endif // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif #include "components/visitedlink/renderer/visitedlink_slave.h" #include "components/web_cache/renderer/web_cache_impl.h" #include "content/public/renderer/render_frame.h" @@ -63,27 +63,42 @@ #include "content/public/common/simple_connection_filter.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" +#include "media/base/key_system_properties.h" +#include "media/media_buildflags.h" #include "net/base/net_errors.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "services/service_manager/public/cpp/service_context.h" +#include "third_party/blink/public/platform/web_url_error.h" +#include "third_party/blink/public/platform/web_url_request.h" +#include "third_party/blink/public/web/web_security_policy.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "content/public/common/web_preferences.h" -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) #include "renderer/print_web_view_helper_delegate_qt.h" -#endif // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif #include "renderer/render_frame_observer_qt.h" #include "renderer/render_view_observer_qt.h" #include "renderer/user_resource_controller.h" +#if QT_CONFIG(webengine_webchannel) #include "renderer/web_channel_ipc_transport.h" +#endif #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" #include "components/grit/components_resources.h" +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +#include "base/feature_list.h" +#include "content/public/renderer/key_system_support.h" +#include "media/base/media_switches.h" +#include "media/base/video_codecs.h" +#include "third_party/widevine/cdm/widevine_cdm_common.h" + #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. +#endif namespace QtWebEngineCore { @@ -100,24 +115,29 @@ ContentRendererClientQt::~ContentRendererClientQt() void ContentRendererClientQt::RenderThreadStarted() { content::RenderThread *renderThread = content::RenderThread::Get(); + (void)GetConnector(); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); m_webCacheImpl.reset(new web_cache::WebCacheImpl()); - auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + m_prescientNetworkingDispatcher.reset(new network_hints::PrescientNetworkingDispatcher()); + + auto registry = std::make_unique<service_manager::BinderRegistry>(); registry->AddInterface(m_visitedLinkSlave->GetBindCallback(), base::ThreadTaskRunnerHandle::Get()); - content::ChildThread::Get() - ->GetServiceManagerConnection() - ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>( - std::move(registry))); - + content::ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( + std::make_unique<content::SimpleConnectionFilter>(std::move(registry))); renderThread->AddObserver(UserResourceController::instance()); -#if BUILDFLAG(ENABLE_SPELLCHECK) - m_spellCheck.reset(new SpellCheck(this)); - renderThread->AddObserver(m_spellCheck.data()); +#if QT_CONFIG(webengine_spellchecker) + if (!m_spellCheck) + InitSpellCheck(); #endif + + // Allow XMLHttpRequests from qrc to file. + blink::WebURL qrc(blink::KURL("qrc:")); + blink::WebString file(blink::WebString::FromASCII("file")); + blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(qrc, file, blink::WebString(), true); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) @@ -130,31 +150,22 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) { new QtWebEngineCore::RenderFrameObserverQt(render_frame); +#if QT_CONFIG(webengine_webchannel) if (render_frame->IsMainFrame()) new WebChannelIPCTransport(render_frame); +#endif UserResourceController::instance()->renderFrameCreated(render_frame); new QtWebEngineCore::ContentSettingsObserverQt(render_frame); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) new SpellCheckProvider(render_frame, m_spellCheck.data(), this); #endif -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) new printing::PrintRenderFrameHelper( render_frame, base::WrapUnique(new PrintWebViewHelperDelegateQt())); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) -} - -void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* render_frame) -{ - // Check whether the render_frame has been created and has not been detached yet. - // Otherwise the WebFrame is not available. - RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame); - if (!render_frame_observer || render_frame_observer->isFrameDetached()) - return; // The frame is invisible to scripts. - - UserResourceController::instance()->RunScriptsAtDocumentStart(render_frame); +#endif // QT_CONFIG(webengine_printing_and_pdf) } void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) @@ -242,201 +253,255 @@ bool ContentRendererClientQt::IsLinkVisited(unsigned long long linkHash) return m_visitedLinkSlave->IsVisited(linkHash); } -void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) +blink::WebPrescientNetworking *ContentRendererClientQt::GetPrescientNetworking() { - content::RenderThread::Get()->GetConnector()->BindInterface(service_manager::Identity("qtwebengine"), - interface_name, - std::move(interface_pipe)); + return m_prescientNetworkingDispatcher.get(); } -// The following is based on chrome/renderer/media/chrome_key_systems.cc: -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE.Chromium file. - -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) -static const char kExternalClearKeyPepperType[] = "application/x-ppapi-clearkey-cdm"; - -static bool IsPepperCdmAvailable(const std::string& pepper_type, - std::vector<content::WebPluginMimeType::Param>* additional_params) +void ContentRendererClientQt::OnStart() { - base::Optional<std::vector<content::WebPluginMimeType::Param>> opt_additional_params; - content::RenderThread::Get()->Send( - new QtWebEngineHostMsg_IsInternalPluginAvailableForMimeType( - pepper_type, - &opt_additional_params)); - - if (opt_additional_params) - *additional_params = *opt_additional_params; - - return opt_additional_params.has_value(); + context()->connector()->BindConnectorRequest(std::move(m_connectorRequest)); } -// KeySystemProperties implementation for external Clear Key systems. -class ExternalClearKeyProperties : public media::KeySystemProperties +void ContentRendererClientQt::OnBindInterface(const service_manager::BindSourceInfo &remote_info, + const std::string& name, + mojo::ScopedMessagePipeHandle handle) { -public: - explicit ExternalClearKeyProperties(const std::string& key_system_name) - : key_system_name_(key_system_name) {} - - std::string GetKeySystemName() const override { return key_system_name_; } - bool IsSupportedInitDataType(media::EmeInitDataType init_data_type) const override - { - switch (init_data_type) { - case media::EmeInitDataType::WEBM: - case media::EmeInitDataType::KEYIDS: - return true; - - case media::EmeInitDataType::CENC: -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - return true; -#else - return false; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) - - case media::EmeInitDataType::UNKNOWN: - return false; - } - NOTREACHED(); - return false; - } - - media::SupportedCodecs GetSupportedCodecs() const override - { -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - return media::EME_CODEC_MP4_ALL | media::EME_CODEC_WEBM_ALL; -#else - return media::EME_CODEC_WEBM_ALL; -#endif - } - - media::EmeConfigRule GetRobustnessConfigRule( - media::EmeMediaType media_type, - const std::string& requested_robustness) const override - { - return requested_robustness.empty() ? media::EmeConfigRule::SUPPORTED - : media::EmeConfigRule::NOT_SUPPORTED; - } - - // Persistent license sessions are faked. - media::EmeSessionTypeSupport GetPersistentLicenseSessionSupport() const override - { - return media::EmeSessionTypeSupport::SUPPORTED; - } - - media::EmeSessionTypeSupport GetPersistentReleaseMessageSessionSupport() const override { - return media::EmeSessionTypeSupport::NOT_SUPPORTED; - } - - media::EmeFeatureSupport GetPersistentStateSupport() const override - { - return media::EmeFeatureSupport::REQUESTABLE; - } - - media::EmeFeatureSupport GetDistinctiveIdentifierSupport() const override - { - return media::EmeFeatureSupport::NOT_SUPPORTED; - } + Q_UNUSED(remote_info); + m_registry.TryBindInterface(name, &handle); +} - std::string GetPepperType() const override - { - return kExternalClearKeyPepperType; - } +void ContentRendererClientQt::GetInterface(const std::string &interface_name, mojo::ScopedMessagePipeHandle interface_pipe) +{ + if (!m_connector) + return; + m_connector->BindInterface(service_manager::Identity("qtwebengine"), + interface_name, + std::move(interface_pipe)); +} -private: - const std::string key_system_name_; -}; +// The following is based on chrome/renderer/media/chrome_key_systems.cc: +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) // External Clear Key (used for testing). static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProperties>>* concrete_key_systems) { + // TODO(xhwang): Move these into an array so we can use a for loop to add + // supported key systems below. static const char kExternalClearKeyKeySystem[] = - "org.chromium.externalclearkey"; + "org.chromium.externalclearkey"; static const char kExternalClearKeyDecryptOnlyKeySystem[] = - "org.chromium.externalclearkey.decryptonly"; + "org.chromium.externalclearkey.decryptonly"; + static const char kExternalClearKeyMessageTypeTestKeySystem[] = + "org.chromium.externalclearkey.messagetypetest"; static const char kExternalClearKeyFileIOTestKeySystem[] = - "org.chromium.externalclearkey.fileiotest"; + "org.chromium.externalclearkey.fileiotest"; + static const char kExternalClearKeyOutputProtectionTestKeySystem[] = + "org.chromium.externalclearkey.outputprotectiontest"; + static const char kExternalClearKeyPlatformVerificationTestKeySystem[] = + "org.chromium.externalclearkey.platformverificationtest"; static const char kExternalClearKeyInitializeFailKeySystem[] = - "org.chromium.externalclearkey.initializefail"; + "org.chromium.externalclearkey.initializefail"; static const char kExternalClearKeyCrashKeySystem[] = - "org.chromium.externalclearkey.crash"; - - std::vector<content::WebPluginMimeType::Param> additional_params; - if (!IsPepperCdmAvailable(kExternalClearKeyPepperType, &additional_params)) + "org.chromium.externalclearkey.crash"; + static const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = + "org.chromium.externalclearkey.verifycdmhosttest"; + static const char kExternalClearKeyStorageIdTestKeySystem[] = + "org.chromium.externalclearkey.storageidtest"; + static const char kExternalClearKeyDifferentGuidTestKeySystem[] = + "org.chromium.externalclearkey.differentguid"; + static const char kExternalClearKeyCdmProxyTestKeySystem[] = + "org.chromium.externalclearkey.cdmproxytest"; + + media::mojom::KeySystemCapabilityPtr capability; + if (!content::IsKeySystemSupported(kExternalClearKeyKeySystem, &capability)) { + DVLOG(1) << "External Clear Key not supported"; return; + } concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyKeySystem)); + new cdm::ExternalClearKeyProperties(kExternalClearKeyKeySystem)); // Add support of decrypt-only mode in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyDecryptOnlyKeySystem)); - // A key system that triggers FileIO test in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem)); + // A key system that triggers various types of messages in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyMessageTypeTestKeySystem)); + + // A key system that triggers the FileIO test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyFileIOTestKeySystem)); + + // A key system that triggers the output protection test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyOutputProtectionTestKeySystem)); + + // A key system that triggers the platform verification test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyPlatformVerificationTestKeySystem)); // A key system that Chrome thinks is supported by ClearKeyCdm, but actually // will be refused by ClearKeyCdm. This is to test the CDM initialization // failure case. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyInitializeFailKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyInitializeFailKeySystem)); // A key system that triggers a crash in ClearKeyCdm. - concrete_key_systems->emplace_back( - new ExternalClearKeyProperties(kExternalClearKeyCrashKeySystem)); + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyCrashKeySystem)); + + // A key system that triggers the verify host files test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyVerifyCdmHostTestKeySystem)); + + // A key system that fetches the Storage ID in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyStorageIdTestKeySystem)); + + // A key system that is registered with a different CDM GUID. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyDifferentGuidTestKeySystem)); + + // A key system that triggers CDM Proxy test in ClearKeyCdm. + concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties( + kExternalClearKeyCdmProxyTestKeySystem)); } #if defined(WIDEVINE_CDM_AVAILABLE) +static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, bool is_secure) +{ + media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; + + // Audio codecs are always supported because the CDM only does decrypt-only + // for audio. The only exception is when |is_secure| is true and there's no + // secure video decoder available, which is a signal that secure hardware + // decryption is not available either. + // TODO(sandersd): Distinguish these from those that are directly supported, + // as those may offer a higher level of protection. + if (!supported_video_codecs.empty() || !is_secure) { + supported_codecs |= media::EME_CODEC_WEBM_OPUS; + supported_codecs |= media::EME_CODEC_WEBM_VORBIS; + supported_codecs |= media::EME_CODEC_MP4_FLAC; +#if BUILDFLAG(USE_PROPRIETARY_CODECS) + supported_codecs |= media::EME_CODEC_MP4_AAC; +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + } + + // Video codecs are determined by what was registered for the CDM. + for (const auto &codec : supported_video_codecs) { + switch (codec) { + case media::VideoCodec::kCodecVP8: + supported_codecs |= media::EME_CODEC_WEBM_VP8; + break; + case media::VideoCodec::kCodecVP9: + supported_codecs |= media::EME_CODEC_WEBM_VP9; + supported_codecs |= media::EME_CODEC_COMMON_VP9; + break; +#if BUILDFLAG(USE_PROPRIETARY_CODECS) + case media::VideoCodec::kCodecH264: + supported_codecs |= media::EME_CODEC_MP4_AVC1; + break; +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + default: + DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec); + break; + } + } -static void AddPepperBasedWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) + return supported_codecs; +} + +static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems) { -//#if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) -// Version glibc_version(gnu_get_libc_version()); -// DCHECK(glibc_version.IsValid()); -// if (glibc_version.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION)) -// return; -//#endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) - - std::vector<content::WebPluginMimeType::Param> additional_params; - if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType, &additional_params)) { + media::mojom::KeySystemCapabilityPtr capability; + if (!content::IsKeySystemSupported(kWidevineKeySystem, &capability)) { DVLOG(1) << "Widevine CDM is not currently available."; return; } media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE; - supported_codecs |= media::EME_CODEC_WEBM_OPUS; - supported_codecs |= media::EME_CODEC_WEBM_VORBIS; - supported_codecs |= media::EME_CODEC_WEBM_VP8; - supported_codecs |= media::EME_CODEC_WEBM_VP9; -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - supported_codecs |= media::EME_CODEC_MP4_AVC1; - supported_codecs |= media::EME_CODEC_MP4_AAC; -#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + // Codecs and encryption schemes. + auto codecs = + GetSupportedCodecs(capability->video_codecs, /*is_secure=*/false); + const auto& encryption_schemes = capability->encryption_schemes; + auto hw_secure_codecs = GetSupportedCodecs(capability->hw_secure_video_codecs, + /*is_secure=*/true); + const auto& hw_secure_encryption_schemes = + capability->hw_secure_encryption_schemes; + // Robustness. using Robustness = cdm::WidevineKeySystemProperties::Robustness; + auto max_audio_robustness = Robustness::SW_SECURE_CRYPTO; + auto max_video_robustness = Robustness::SW_SECURE_DECODE; + + if (base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) { + max_audio_robustness = Robustness::HW_SECURE_CRYPTO; + max_video_robustness = Robustness::HW_SECURE_ALL; + } + + // Session types. + bool cdm_supports_temporary_session = base::ContainsValue(capability->session_types, media::CdmSessionType::kTemporary); + if (!cdm_supports_temporary_session) { + DVLOG(1) << "Temporary session must be supported."; + return; + } + + bool cdm_supports_persistent_license = + base::ContainsValue(capability->session_types, media::CdmSessionType::kPersistentLicense); + auto persistent_license_support = media::EmeSessionTypeSupport::NOT_SUPPORTED; + auto persistent_usage_record_support = media::EmeSessionTypeSupport::NOT_SUPPORTED; + + // Others. + auto persistent_state_support = media::EmeFeatureSupport::REQUESTABLE; + auto distinctive_identifier_support = media::EmeFeatureSupport::NOT_SUPPORTED; + concrete_key_systems->emplace_back(new cdm::WidevineKeySystemProperties( - supported_codecs, - Robustness::SW_SECURE_CRYPTO, // Maximum audio robustness. - Robustness::SW_SECURE_DECODE, // Maximum video robustness. - media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-license. - media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-release-message. - media::EmeFeatureSupport::REQUESTABLE, // Persistent state. - media::EmeFeatureSupport::NOT_SUPPORTED)); // Distinctive identifier. + codecs, encryption_schemes, hw_secure_codecs, + hw_secure_encryption_schemes, max_audio_robustness, max_video_robustness, + persistent_license_support, persistent_usage_record_support, + persistent_state_support, distinctive_identifier_support)); } -#endif // defined(WIDEVINE_CDM_AVAILABLE) -#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) +#endif // defined(WIDEVINE_CDM_AVAILABLE) +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems) { #if BUILDFLAG(ENABLE_LIBRARY_CDMS) - AddExternalClearKey(key_systems); + if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) + AddExternalClearKey(key_systems); #if defined(WIDEVINE_CDM_AVAILABLE) - AddPepperBasedWidevine(key_systems); -#endif // defined(WIDEVINE_CDM_AVAILABLE) -#endif // BUILDFLAG(ENABLE_PEPPER_CDMS) + AddWidevine(key_systems); +#endif // defined(WIDEVINE_CDM_AVAILABLE) + +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) +} + +#if QT_CONFIG(webengine_spellchecker) +void ContentRendererClientQt::InitSpellCheck() +{ + m_spellCheck.reset(new SpellCheck(&m_registry, this)); +} +#endif + +void ContentRendererClientQt::CreateRendererService(service_manager::mojom::ServiceRequest service_request) +{ + m_serviceContext = std::make_unique<service_manager::ServiceContext>( + std::make_unique<service_manager::ForwardingService>(this), + std::move(service_request)); +} + +service_manager::Connector* ContentRendererClientQt::GetConnector() +{ + if (!m_connector) + m_connector = service_manager::Connector::Create(&m_connectorRequest); + return m_connector.get(); } } // namespace diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index b91f57fc2..2a353caa6 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -39,9 +39,13 @@ #ifndef CONTENT_RENDERER_CLIENT_QT_H #define CONTENT_RENDERER_CLIENT_QT_H +#include "qtwebenginecoreglobal_p.h" #include "content/public/renderer/content_renderer_client.h" -#include "components/spellcheck/spellcheck_build_features.h" +#include "components/spellcheck/spellcheck_buildflags.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/local_interface_provider.h" +#include "services/service_manager/public/cpp/service.h" #include <QScopedPointer> @@ -49,6 +53,10 @@ namespace error_page { class Error; } +namespace network_hints { +class PrescientNetworkingDispatcher; +} + namespace visitedlink { class VisitedLinkSlave; } @@ -57,18 +65,21 @@ namespace web_cache { class WebCacheImpl; } -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) class SpellCheck; #endif namespace QtWebEngineCore { class ContentRendererClientQt : public content::ContentRendererClient + , public service_manager::Service , public service_manager::LocalInterfaceProvider { public: ContentRendererClientQt(); ~ContentRendererClientQt(); + + // content::ContentRendererClient: void RenderThreadStarted() override; void RenderViewCreated(content::RenderView *render_view) override; void RenderFrameCreated(content::RenderFrame* render_frame) override; @@ -82,24 +93,44 @@ public: unsigned long long VisitedLinkHash(const char *canonicalUrl, size_t length) override; bool IsLinkVisited(unsigned long long linkHash) override; + blink::WebPrescientNetworking* GetPrescientNetworking() override; void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) override; - void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override; void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override; + void CreateRendererService(service_manager::mojom::ServiceRequest service_request) override; + private: +#if BUILDFLAG(ENABLE_SPELLCHECK) + void InitSpellCheck(); +#endif + service_manager::Connector *GetConnector(); + + // service_manager::Service: + void OnStart() override; + void OnBindInterface(const service_manager::BindSourceInfo &remote_info, + const std::string &name, + mojo::ScopedMessagePipeHandle handle) override; + // service_manager::LocalInterfaceProvider: void GetInterface(const std::string& name, mojo::ScopedMessagePipeHandle request_handle) override; void GetNavigationErrorStringsInternal(content::RenderFrame* renderFrame, const blink::WebURLRequest& failedRequest, const error_page::Error& error, std::string* errorHtml, base::string16* errorDescription); - QScopedPointer<visitedlink::VisitedLinkSlave> m_visitedLinkSlave; QScopedPointer<web_cache::WebCacheImpl> m_webCacheImpl; -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) QScopedPointer<SpellCheck> m_spellCheck; #endif + + std::unique_ptr<service_manager::Connector> m_connector; + service_manager::mojom::ConnectorRequest m_connectorRequest; + std::unique_ptr<service_manager::ServiceContext> m_serviceContext; + service_manager::BinderRegistry m_registry; + std::unique_ptr<network_hints::PrescientNetworkingDispatcher> m_prescientNetworkingDispatcher; + + DISALLOW_COPY_AND_ASSIGN(ContentRendererClientQt); }; } // namespace diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp index bfd0c96f8..045098457 100644 --- a/src/core/renderer/content_settings_observer_qt.cpp +++ b/src/core/renderer/content_settings_observer_qt.cpp @@ -45,10 +45,10 @@ #include "content_settings_observer_qt.h" #include "content/public/renderer/render_frame.h" -#include "third_party/WebKit/public/platform/WebContentSettingCallbacks.h" -#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/blink/public/platform/web_content_setting_callbacks.h" +#include "third_party/blink/public/platform/web_security_origin.h" +#include "third_party/blink/public/web/web_plugin_document.h" +#include "third_party/blink/public/web/web_local_frame.h" #include "url/origin.h" #include "common/qt_messages.h" diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h index 07dcbe350..981655f20 100644 --- a/src/core/renderer/content_settings_observer_qt.h +++ b/src/core/renderer/content_settings_observer_qt.h @@ -47,7 +47,7 @@ #include "base/containers/flat_map.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" -#include "third_party/WebKit/public/platform/WebContentSettingsClient.h" +#include "third_party/blink/public/platform/web_content_settings_client.h" #include "url/gurl.h" namespace blink { diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp index 4a17f7dec..e693cf096 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -42,7 +42,7 @@ // found in the LICENSE.Chromium file. #include "print_web_view_helper_delegate_qt.h" -#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/blink/public/web/web_element.h" #include "web_engine_library_info.h" namespace QtWebEngineCore { @@ -53,7 +53,7 @@ PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() bool PrintWebViewHelperDelegateQt::CancelPrerender(content::RenderFrame *) { - return true; + return false; } blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame* frame) @@ -63,7 +63,7 @@ blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFra bool PrintWebViewHelperDelegateQt::IsPrintPreviewEnabled() { - return false; + return true; } bool PrintWebViewHelperDelegateQt::OverridePrint(blink::WebLocalFrame* frame) diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index 727bf5b92..5a630357c 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -68,7 +68,7 @@ void RenderFrameObserverQt::OnDestruct() { delete this; } -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host) { host->GetPpapiHost()->AddHostFactoryFilter( diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index ac098a961..bca45bd8e 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -40,11 +40,10 @@ #ifndef RENDER_FRAME_OBSERVER_QT_H #define RENDER_FRAME_OBSERVER_QT_H +#include "qtwebenginecoreglobal_p.h" #include "base/compiler_specific.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" -#include "ppapi/features/features.h" - namespace content { class RenderFrame; @@ -60,7 +59,7 @@ public: explicit RenderFrameObserverQt(content::RenderFrame* render_frame); ~RenderFrameObserverQt(); -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; #endif void OnDestruct() override; diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp index 4893a5188..07dadfd40 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/render_view_observer_qt.cpp @@ -43,13 +43,13 @@ #include "components/web_cache/renderer/web_cache_impl.h" #include "content/public/renderer/render_view.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebFrameContentDumper.h" -#include "third_party/WebKit/public/web/WebFrameWidget.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/public/web/web_element.h" +#include "third_party/blink/public/web/web_frame.h" +#include "third_party/blink/public/web/web_frame_content_dumper.h" +#include "third_party/blink/public/web/web_frame_widget.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_view.h" RenderViewObserverQt::RenderViewObserverQt( content::RenderView* render_view, @@ -78,11 +78,6 @@ void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text.Utf16())); } -void RenderViewObserverQt::onSetBackgroundColor(quint32 color) -{ - render_view()->GetWebFrameWidget()->SetBaseBackgroundColor(color); -} - void RenderViewObserverQt::OnDestruct() { delete this; @@ -94,7 +89,6 @@ bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message) IPC_BEGIN_MESSAGE_MAP(RenderViewObserverQt, message) IPC_MESSAGE_HANDLER(RenderViewObserverQt_FetchDocumentMarkup, onFetchDocumentMarkup) IPC_MESSAGE_HANDLER(RenderViewObserverQt_FetchDocumentInnerText, onFetchDocumentInnerText) - IPC_MESSAGE_HANDLER(RenderViewObserverQt_SetBackgroundColor, onSetBackgroundColor) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h index abb472f02..83c0cd265 100644 --- a/src/core/renderer/render_view_observer_qt.h +++ b/src/core/renderer/render_view_observer_qt.h @@ -55,7 +55,6 @@ public: private: void onFetchDocumentMarkup(quint64 requestId); void onFetchDocumentInnerText(quint64 requestId); - void onSetBackgroundColor(quint32 color); void OnDestruct() override; diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 860f94a52..920fda72e 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -47,10 +47,10 @@ #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_view_observer.h" #include "extensions/common/url_pattern.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebScriptSource.h" -#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_script_source.h" +#include "third_party/blink/public/web/web_view.h" #include "v8/include/v8.h" #include "common/qt_messages.h" @@ -60,6 +60,8 @@ #include <QRegularExpression> +#include <bitset> + Q_GLOBAL_STATIC(UserResourceController, qt_webengine_userResourceController) static content::RenderView * const globalScriptsIndex = 0; @@ -134,12 +136,11 @@ public: RenderFrameObserverHelper(content::RenderFrame* render_frame); private: - ~RenderFrameObserverHelper() override; - // RenderFrameObserver implementation. + void DidCommitProvisionalLoad(bool is_new_navigation, bool is_same_document_navigation) override; + void DidClearWindowObject() override; void DidFinishDocumentLoad() override; void DidFinishLoad() override; - void DidStartProvisionalLoad(blink::WebDocumentLoader *document_loader) override; void FrameDetached() override; void OnDestruct() override; bool OnMessageReceived(const IPC::Message& message) override; @@ -148,12 +149,31 @@ private: void onUserScriptRemoved(const UserScriptData &); void onScriptsCleared(); - void runScripts(UserScriptData::InjectionPoint, blink::WebLocalFrame *); + class Runner; + QScopedPointer<Runner> m_runner; +}; + +// Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to +// avoid running scripts more than once per injection point. +class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner> { +public: + explicit Runner(blink::WebLocalFrame *frame) + : m_frame(frame) + { + } - // Set of frames which are pending to get an AfterLoad invocation of runScripts, if they - // haven't gotten it already. - QSet<blink::WebLocalFrame *> m_pendingFrames; - base::WeakPtrFactory<RenderFrameObserverHelper> m_weakPtrFactory; + void run(UserScriptData::InjectionPoint p) + { + DCHECK_LT(p, m_ran.size()); + if (!m_ran[p]) { + UserResourceController::instance()->runScripts(p, m_frame); + m_ran[p] = true; + } + } + +private: + blink::WebLocalFrame *m_frame; + std::bitset<3> m_ran; }; // Used only for script cleanup on RenderView destruction. @@ -166,14 +186,6 @@ private: void OnDestruct() override; }; -void UserResourceController::RenderFrameObserverHelper::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) -{ - if (p == UserScriptData::AfterLoad && !m_pendingFrames.remove(frame)) - return; - - UserResourceController::instance()->runScripts(p, frame); -} - void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame) { content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame); @@ -188,7 +200,7 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink: QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(0).toList(); scriptsToRun.append(m_viewUserScriptMap.value(renderView).toList()); - Q_FOREACH (uint64_t id, scriptsToRun) { + for (uint64_t id : qAsConst(scriptsToRun)) { const UserScriptData &script = m_scripts.value(id); if (script.injectionPoint != p || (!script.injectForSubframes && !isMainFrame)) @@ -197,66 +209,71 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink: continue; blink::WebScriptSource source(blink::WebString::FromUTF8(script.source), script.url); if (script.worldId) - frame->ExecuteScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1); + frame->ExecuteScriptInIsolatedWorld(script.worldId, source); else frame->ExecuteScript(source); } } -void UserResourceController::RunScriptsAtDocumentStart(content::RenderFrame *render_frame) -{ - runScripts(UserScriptData::DocumentElementCreation, render_frame->GetWebFrame()); -} - void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) { runScripts(UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame()); } UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(content::RenderFrame *render_frame) - : content::RenderFrameObserver(render_frame), m_weakPtrFactory(this) + : content::RenderFrameObserver(render_frame) { } -UserResourceController::RenderFrameObserverHelper::~RenderFrameObserverHelper() +UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view) + : content::RenderViewObserver(render_view) { - m_weakPtrFactory.InvalidateWeakPtrs(); } -UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view) - : content::RenderViewObserver(render_view) +void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool /* is_new_navigation */, + bool is_same_document_navigation) { + if (is_same_document_navigation) + return; + + // We are almost ready to run scripts. We still have to wait until the host + // process has been notified of the DidCommitProvisionalLoad event to ensure + // that the WebChannelTransportHost is ready to receive messages. + + m_runner.reset(new Runner(render_frame()->GetWebFrame())); } -void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() +void UserResourceController::RenderFrameObserverHelper::DidClearWindowObject() { - blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); - m_pendingFrames.insert(frame); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderFrameObserverHelper::runScripts, - m_weakPtrFactory.GetWeakPtr(), UserScriptData::AfterLoad, frame), - base::TimeDelta::FromMilliseconds(afterLoadTimeout)); + // This is called both before and after DidCommitProvisionalLoad, non-null + // m_runner means it's after. + if (m_runner) + m_runner->run(UserScriptData::DocumentElementCreation); } -void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() +void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad() { - blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); + // Don't run scripts if provisional load failed (DidFailProvisionalLoad + // called instead of DidCommitProvisionalLoad). + if (m_runner) + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad), + base::TimeDelta::FromMilliseconds(afterLoadTimeout)); - // DidFinishDocumentLoad always comes before this, so frame has already been marked as pending. - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&UserResourceController::RenderFrameObserverHelper::runScripts, - m_weakPtrFactory.GetWeakPtr(), UserScriptData::AfterLoad, frame)); } -void UserResourceController::RenderFrameObserverHelper::DidStartProvisionalLoad(blink::WebDocumentLoader *document_loader) +void UserResourceController::RenderFrameObserverHelper::DidFinishLoad() { - Q_UNUSED(document_loader); - blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); - m_pendingFrames.remove(frame); + if (m_runner) + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad)); } void UserResourceController::RenderFrameObserverHelper::FrameDetached() { - blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); - m_pendingFrames.remove(frame); + m_runner.reset(); } void UserResourceController::RenderFrameObserverHelper::OnDestruct() @@ -326,7 +343,7 @@ UserResourceController::UserResourceController() { #if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) static bool onlyCalledOnce = true; - Q_ASSERT(onlyCalledOnce); + DCHECK(onlyCalledOnce); onlyCalledOnce = false; #endif // !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) } @@ -348,7 +365,7 @@ void UserResourceController::renderViewDestroyed(content::RenderView *renderView ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(renderView); if (it == m_viewUserScriptMap.end()) // ASSERT maybe? return; - Q_FOREACH (uint64_t id, it.value()) { + for (uint64_t id : qAsConst(it.value())) { m_scripts.remove(id); } m_viewUserScriptMap.remove(renderView); @@ -379,7 +396,7 @@ void UserResourceController::clearScriptsForView(content::RenderView *view) ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view); if (it == m_viewUserScriptMap.end()) return; - Q_FOREACH (uint64_t id, it.value()) + for (uint64_t id : qAsConst(it.value())) m_scripts.remove(id); m_viewUserScriptMap.remove(view); diff --git a/src/core/renderer/user_resource_controller.h b/src/core/renderer/user_resource_controller.h index 50af24243..0b5e0a0c6 100644 --- a/src/core/renderer/user_resource_controller.h +++ b/src/core/renderer/user_resource_controller.h @@ -68,7 +68,6 @@ public: void removeScriptForView(const UserScriptData &, content::RenderView *); void clearScriptsForView(content::RenderView *); - void RunScriptsAtDocumentStart(content::RenderFrame *render_frame); void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame); private: diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index ef00bcef3..1f496e810 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -49,9 +49,13 @@ #include "gin/handle.h" #include "gin/object_template_builder.h" #include "gin/wrappable.h" -#include "third_party/WebKit/public/web/WebKit.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/blink/public/web/blink.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "v8/include/v8.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include <QJsonDocument> @@ -154,9 +158,9 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) int size = 0; const char *rawData = doc.rawData(&size); - renderFrame->Send(new WebChannelIPCTransportHost_SendMessage( - renderFrame->GetRoutingID(), - std::vector<char>(rawData, rawData + size))); + qtwebchannel::mojom::WebChannelTransportHostAssociatedPtr webChannelTransport; + renderFrame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->DispatchWebChannelMessage(std::vector<uint8_t>(rawData, rawData + size)); } gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) @@ -167,29 +171,50 @@ gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Iso WebChannelIPCTransport::WebChannelIPCTransport(content::RenderFrame *renderFrame) : content::RenderFrameObserver(renderFrame) + , m_worldId(0) + , m_worldInitialized(false) { + renderFrame->GetAssociatedInterfaceRegistry()->AddInterface( + base::Bind(&WebChannelIPCTransport::BindRequest, base::Unretained(this))); } -void WebChannelIPCTransport::setWorldId(base::Optional<uint> worldId) +void WebChannelIPCTransport::BindRequest( + qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request) { + + m_binding.AddBinding(this, std::move(request)); +} + +void WebChannelIPCTransport::SetWorldId(uint32_t worldId) { - if (m_worldId == worldId) + if (m_worldInitialized && m_worldId == worldId) return; - if (m_worldId && m_canUseContext) - WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), *m_worldId); + if (m_worldInitialized && m_canUseContext) + WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); + m_worldInitialized = true; m_worldId = worldId; - if (m_worldId && m_canUseContext) - WebChannelTransport::Install(render_frame()->GetWebFrame(), *m_worldId); + if (m_canUseContext) + WebChannelTransport::Install(render_frame()->GetWebFrame(), m_worldId); +} + +void WebChannelIPCTransport::ResetWorldId() +{ + if (m_worldInitialized && m_canUseContext) + WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); + + m_worldInitialized = false; + m_worldId = 0; } -void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJson, uint worldId) +void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson, uint32_t worldId) { DCHECK(m_canUseContext); DCHECK(m_worldId == worldId); - QJsonDocument doc = QJsonDocument::fromRawData(binaryJson.data(), binaryJson.size(), QJsonDocument::BypassValidation); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), + binaryJson.size(), QJsonDocument::BypassValidation); DCHECK(doc.isObject()); QByteArray json = doc.toJson(QJsonDocument::Compact); @@ -241,22 +266,11 @@ void WebChannelIPCTransport::DidClearWindowObject() { if (!m_canUseContext) { m_canUseContext = true; - if (m_worldId) - WebChannelTransport::Install(render_frame()->GetWebFrame(), *m_worldId); + if (m_worldInitialized) + WebChannelTransport::Install(render_frame()->GetWebFrame(), m_worldId); } } -bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) -{ - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransport, message) - IPC_MESSAGE_HANDLER(WebChannelIPCTransport_SetWorldId, setWorldId) - IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - void WebChannelIPCTransport::OnDestruct() { delete this; diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 19494360a..178c20ed1 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -41,30 +41,39 @@ #define WEB_CHANNEL_IPC_TRANSPORT_H #include "content/public/renderer/render_frame_observer.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "mojo/public/cpp/bindings/associated_binding_set.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include <QtCore/qglobal.h> namespace QtWebEngineCore { -class WebChannelIPCTransport : private content::RenderFrameObserver { +class WebChannelIPCTransport: private content::RenderFrameObserver, + public qtwebchannel::mojom::WebChannelTransportRender { public: WebChannelIPCTransport(content::RenderFrame *); private: - void setWorldId(base::Optional<uint> worldId); - void dispatchWebChannelMessage(const std::vector<char> &binaryJson, uint worldId); + // qtwebchannel::mojom::WebChannelTransportRender + void SetWorldId(uint32_t worldId) override; + void ResetWorldId() override; + void DispatchWebChannelMessage(const std::vector<uint8_t>& binaryJson, uint32_t worldId) override; // RenderFrameObserver void WillReleaseScriptContext(v8::Local<v8::Context> context, int worldId) override; void DidClearWindowObject() override; - bool OnMessageReceived(const IPC::Message &message) override; void OnDestruct() override; + void BindRequest(qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request); +private: // The worldId from our WebChannelIPCTransportHost or empty when there is no // WebChannelIPCTransportHost. - base::Optional<uint> m_worldId; + uint32_t m_worldId; + bool m_worldInitialized; // True means it's currently OK to manipulate the frame's script context. bool m_canUseContext = false; + mojo::AssociatedBindingSet<qtwebchannel::mojom::WebChannelTransportRender> m_binding; }; } // namespace diff --git a/src/core/renderer_host/user_resource_controller_host.cpp b/src/core/renderer_host/user_resource_controller_host.cpp index a9071df8f..ed4d736f2 100644 --- a/src/core/renderer_host/user_resource_controller_host.cpp +++ b/src/core/renderer_host/user_resource_controller_host.cpp @@ -42,8 +42,6 @@ #include "common/qt_messages.h" #include "type_conversion.h" #include "web_contents_adapter.h" -#include "web_contents_adapter_p.h" - #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/render_view_host.h" @@ -77,7 +75,8 @@ void UserResourceControllerHost::WebContentsObserverHelper::RenderFrameCreated( content::RenderFrameHost *renderFrameHost) { content::WebContents *contents = web_contents(); - Q_FOREACH (const UserScript &script, m_controllerHost->m_perContentsScripts.value(contents)) + const QList<UserScript> scripts = m_controllerHost->m_perContentsScripts.value(contents); + for (const UserScript &script : scripts) renderFrameHost->Send(new RenderFrameObserverHelper_AddScript( renderFrameHost->GetRoutingID(), script.data())); } @@ -124,7 +123,7 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont if (isProfileWideScript) { if (!m_profileWideScripts.contains(script)) { m_profileWideScripts.append(script); - Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) + for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) renderer->Send(new UserResourceController_AddScript(script.data())); } } else { @@ -170,7 +169,7 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); if (it == m_profileWideScripts.end()) return false; - Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) + for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) renderer->Send(new UserResourceController_RemoveScript((*it).data())); m_profileWideScripts.erase(it); } else { @@ -195,7 +194,7 @@ void UserResourceControllerHost::clearAllScripts(WebContentsAdapter *adapter) const bool isProfileWideScript = !adapter; if (isProfileWideScript) { m_profileWideScripts.clear(); - Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) + for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) renderer->Send(new UserResourceController_ClearScripts); } else { content::WebContents *contents = adapter->webContents(); @@ -231,7 +230,7 @@ void UserResourceControllerHost::renderProcessStartedWithHost(content::RenderPro m_renderProcessObserver.reset(new RenderProcessObserverHelper(this)); renderer->AddObserver(m_renderProcessObserver.data()); m_observedProcesses.insert(renderer); - Q_FOREACH (const UserScript &script, m_profileWideScripts) + for (const UserScript &script : qAsConst(m_profileWideScripts)) renderer->Send(new UserResourceController_AddScript(script.data())); } @@ -246,7 +245,7 @@ UserResourceControllerHost::UserResourceControllerHost() UserResourceControllerHost::~UserResourceControllerHost() { - Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) + for (content::RenderProcessHost *renderer : qAsConst(m_observedProcesses)) renderer->RemoveObserver(m_renderProcessObserver.data()); } diff --git a/src/core/renderer_host/user_resource_controller_host.h b/src/core/renderer_host/user_resource_controller_host.h index 8e6e1e3bf..40b685163 100644 --- a/src/core/renderer_host/user_resource_controller_host.h +++ b/src/core/renderer_host/user_resource_controller_host.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef USER_RESOURCE_CONTROLLER_HOST_H #define USER_RESOURCE_CONTROLLER_HOST_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QtCore/QSet> #include <QtCore/QScopedPointer> @@ -54,9 +65,8 @@ class WebContents; namespace QtWebEngineCore { class WebContentsAdapter; -class WebContentsAdapterPrivate; -class QWEBENGINE_EXPORT UserResourceControllerHost { +class QWEBENGINECORE_PRIVATE_EXPORT UserResourceControllerHost { public: UserResourceControllerHost(); diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index d99dfde97..e1929e4cd 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -42,7 +42,10 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" - +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include "common/qt_messages.h" #include <QJsonDocument> @@ -72,13 +75,21 @@ inline QDebug operator<<(QDebug stream, const base::Optional<T> &opt) WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *contents, uint worldId, QObject *parent) : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) + , m_worldId(worldId) + , m_binding(contents, this) { - setWorldId(worldId); + for (content::RenderFrameHost *frame : contents->GetAllFrames()) + setWorldId(frame, worldId); } WebChannelIPCTransportHost::~WebChannelIPCTransportHost() { - setWorldId(base::nullopt); + resetWorldId(); +} + +uint WebChannelIPCTransportHost::worldId() const +{ + return m_worldId; } void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) @@ -87,11 +98,13 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) int size = 0; const char *rawData = doc.rawData(&size); content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; - frame->Send(new WebChannelIPCTransport_Message(frame->GetRoutingID(), std::vector<char>(rawData, rawData + size), *m_worldId)); + webChannelTransport->DispatchWebChannelMessage(std::vector<uint8_t>(rawData, rawData + size), m_worldId); } -void WebChannelIPCTransportHost::setWorldId(base::Optional<uint> worldId) +void WebChannelIPCTransportHost::setWorldId(uint32_t worldId) { if (m_worldId == worldId) return; @@ -100,23 +113,41 @@ void WebChannelIPCTransportHost::setWorldId(base::Optional<uint> worldId) m_worldId = worldId; } -void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, base::Optional<uint> worldId) +void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, uint32_t worldId) { if (!frame->IsRenderFrameLive()) return; qCDebug(log).nospace() << "sending setWorldId(" << worldId << ") message to " << frame; - frame->Send(new WebChannelIPCTransport_SetWorldId(frame->GetRoutingID(), worldId)); + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->SetWorldId(worldId); } -void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message) +void WebChannelIPCTransportHost::resetWorldId() +{ + for (content::RenderFrameHost *frame : web_contents()->GetAllFrames()) { + if (!frame->IsRenderFrameLive()) + return; + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->ResetWorldId(); + } +} + +void WebChannelIPCTransportHost::DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson) { content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + if (m_binding.GetCurrentTargetFrame() != frame) { + return; + } + QJsonDocument doc; // QJsonDocument::fromRawData does not check the length before it starts // parsing the QJsonPrivate::Header and QJsonPrivate::Base structures. - if (message.size() >= sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)) - doc = QJsonDocument::fromRawData(message.data(), message.size()); + if (binaryJson.size() >= sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)) + doc = QJsonDocument::fromRawData(reinterpret_cast<const char *>(binaryJson.data()), + binaryJson.size()); if (!doc.isObject()) { qCCritical(log).nospace() << "received invalid webchannel message from " << frame; @@ -132,17 +163,4 @@ void WebChannelIPCTransportHost::RenderFrameCreated(content::RenderFrameHost *fr setWorldId(frame, m_worldId); } -bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost *receiver) -{ - if (receiver != web_contents()->GetMainFrame()) - return false; - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransportHost, message) - IPC_MESSAGE_HANDLER(WebChannelIPCTransportHost_SendMessage, onWebChannelMessage) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - } // namespace QtWebEngineCore diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.h b/src/core/renderer_host/web_channel_ipc_transport_host.h index 3a814a794..94891f25f 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -43,6 +43,9 @@ #include "qtwebenginecoreglobal.h" #include "content/public/browser/web_contents_observer.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "content/public/browser/web_contents_binding_set.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include <QWebChannelAbstractTransport> @@ -51,29 +54,33 @@ QT_FORWARD_DECLARE_CLASS(QString) namespace QtWebEngineCore { class WebChannelIPCTransportHost : public QWebChannelAbstractTransport - , private content::WebContentsObserver { + , private content::WebContentsObserver + , qtwebchannel::mojom::WebChannelTransportHost { public: - WebChannelIPCTransportHost(content::WebContents *webContents, uint worldId = 0, QObject *parent = nullptr); - virtual ~WebChannelIPCTransportHost(); + WebChannelIPCTransportHost(content::WebContents *webContents, uint32_t worldId = 0, QObject *parent = nullptr); + ~WebChannelIPCTransportHost() override; - void setWorldId(uint worldId) { setWorldId(base::Optional<uint>(worldId)); } - uint worldId() const { return *m_worldId; } + void setWorldId(uint32_t worldId); + uint32_t worldId() const; // QWebChannelAbstractTransport void sendMessage(const QJsonObject &message) override; private: - void setWorldId(base::Optional<uint> worldId); - void setWorldId(content::RenderFrameHost *frame, base::Optional<uint> worldId); + void setWorldId(content::RenderFrameHost *frame, uint32_t worldId); + void resetWorldId(); void onWebChannelMessage(const std::vector<char> &message); // WebContentsObserver void RenderFrameCreated(content::RenderFrameHost *frame) override; - bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost *receiver) override; + + // qtwebchannel::mojom::WebChannelTransportHost + void DispatchWebChannelMessage(const std::vector<uint8_t> &binaryJson) override; // Empty only during construction/destruction. Synchronized to all the // WebChannelIPCTransports/RenderFrames in the observed WebContents. - base::Optional<uint> m_worldId; + uint32_t m_worldId; + content::WebContentsFrameBindingSet<qtwebchannel::mojom::WebChannelTransportHost> m_binding; }; } // namespace diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp index c37854ea6..428faa34e 100644 --- a/src/core/resource_bundle_qt.cpp +++ b/src/core/resource_bundle_qt.cpp @@ -40,6 +40,7 @@ #include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "content/public/common/content_switches.h" +#include "services/service_manager/sandbox/switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/data_pack.h" #include "ui/base/resource/resource_bundle.h" @@ -75,7 +76,7 @@ bool ResourceBundle::LocaleDataPakExists(const std::string& locale) #if defined(OS_LINUX) base::CommandLine *parsed_command_line = base::CommandLine::ForCurrentProcess(); std::string process_type = parsed_command_line->GetSwitchValueASCII(switches::kProcessType); - bool no_sandbox = parsed_command_line->HasSwitch(switches::kNoSandbox); + bool no_sandbox = parsed_command_line->HasSwitch(service_manager::switches::kNoSandbox); if (process_type == switches::kRendererProcess && !no_sandbox) { // The Renderer Process is sandboxed thus only one locale is available in it. // The particular one is passed by the --lang command line option. diff --git a/src/core/resource_context_qt.cpp b/src/core/resource_context_qt.cpp index 1ab1ea223..6dfa5064e 100644 --- a/src/core/resource_context_qt.cpp +++ b/src/core/resource_context_qt.cpp @@ -39,24 +39,29 @@ #include "resource_context_qt.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "net/dns/host_resolver.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" +#include "profile_io_data_qt.h" -#include "browser_context_qt.h" +#include <qglobal.h> namespace QtWebEngineCore { -net::HostResolver *ResourceContextQt::GetHostResolver() +ResourceContextQt::ResourceContextQt(ProfileIODataQt *io_data) + : m_io_data(io_data) { - return GetRequestContext()->host_resolver(); } net::URLRequestContext* ResourceContextQt::GetRequestContext() { - Q_ASSERT(context); + Q_ASSERT(m_io_data); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // FIXME: This is the only remaining use of GetRequestContext(), // but we are on the wrong thread for calling BrowserContext::GetDefaultStoragePartition - return context->GetRequestContext()->GetURLRequestContext(); + return m_io_data->urlRequestContext(); } } // namespace QtWebEngineCore diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h index 62452b449..6a5e7a74e 100644 --- a/src/core/resource_context_qt.h +++ b/src/core/resource_context_qt.h @@ -42,28 +42,17 @@ #include "content/public/browser/resource_context.h" -namespace net { -class URLRequestContextGetter; -} - -class GURL; - namespace QtWebEngineCore { -class BrowserContextQt; + +class ProfileIODataQt; class ResourceContextQt : public content::ResourceContext { public: - ResourceContextQt(BrowserContextQt *ctx) - : context(ctx) - {} - - net::HostResolver *GetHostResolver() override; + ResourceContextQt(ProfileIODataQt *io_data); net::URLRequestContext *GetRequestContext() override; - private: - BrowserContextQt *context; - + ProfileIODataQt* m_io_data; DISALLOW_COPY_AND_ASSIGN(ResourceContextQt); }; diff --git a/src/core/service/service_qt.cpp b/src/core/service/service_qt.cpp new file mode 100644 index 000000000..30ed269e8 --- /dev/null +++ b/src/core/service/service_qt.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +// based on chrome/browser/chrome_service.cc: +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "service_qt.h" + +#include "base/no_destructor.h" +#include "components/spellcheck/spellcheck_buildflags.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/service_context.h" + +#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" +#endif + +class ServiceQt::IOThreadContext : public service_manager::Service { +public: + IOThreadContext(); + ~IOThreadContext() override = default; + + void BindConnector(service_manager::mojom::ConnectorRequest connector_request); + +private: + void BindConnectorOnIOThread(service_manager::mojom::ConnectorRequest connector_request); + + // service_manager::Service: + void OnStart() override; + void OnBindInterface(const service_manager::BindSourceInfo &remote_info, + const std::string &name, + mojo::ScopedMessagePipeHandle handle) override; + + service_manager::mojom::ConnectorRequest m_connectorRequest; + service_manager::BinderRegistry m_registry; + service_manager::BinderRegistryWithArgs<const service_manager::BindSourceInfo&> m_registry_with_source_info; + + DISALLOW_COPY_AND_ASSIGN(IOThreadContext); +}; + +ServiceQt::IOThreadContext::IOThreadContext() +{ + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner = + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI); +#if BUILDFLAG(ENABLE_SPELLCHECK) + m_registry_with_source_info.AddInterface(base::Bind(&SpellCheckHostChromeImpl::Create), ui_task_runner); +#endif +} + +void ServiceQt::IOThreadContext::BindConnector(service_manager::mojom::ConnectorRequest connector_request) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // NOTE: It's not safe to modify |connector_request_| here since it's read + // on the IO thread. Post a task instead. As long as this task is posted + // before any code attempts to connect to the chrome service, there's no + // race. + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)->PostTask( + FROM_HERE, + base::BindOnce(&IOThreadContext::BindConnectorOnIOThread, + base::Unretained(this), + std::move(connector_request))); +} + +void ServiceQt::IOThreadContext::BindConnectorOnIOThread(service_manager::mojom::ConnectorRequest connector_request) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + m_connectorRequest = std::move(connector_request); +} + +void ServiceQt::IOThreadContext::OnStart() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK(m_connectorRequest.is_pending()); + context()->connector()->BindConnectorRequest(std::move(m_connectorRequest)); +} + +void ServiceQt::IOThreadContext::OnBindInterface(const service_manager::BindSourceInfo &remote_info, + const std::string &name, + mojo::ScopedMessagePipeHandle handle) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + content::OverrideOnBindInterface(remote_info, name, &handle); + if (!handle.is_valid()) + return; + + if (!m_registry.TryBindInterface(name, &handle)) + m_registry_with_source_info.TryBindInterface(name, &handle, remote_info); +} + +ServiceQt *ServiceQt::GetInstance() +{ + static base::NoDestructor<ServiceQt> service; + return service.get(); +} + +service_manager::EmbeddedServiceInfo::ServiceFactory ServiceQt::CreateServiceQtFactory() +{ + return base::BindRepeating(&ServiceQt::CreateServiceQtWrapper, base::Unretained(this)); +} + +ServiceQt::ServiceQt() : m_ioThreadContext(std::make_unique<IOThreadContext>()) +{} + +ServiceQt::~ServiceQt() = default; + +void ServiceQt::InitConnector() +{ + service_manager::mojom::ConnectorRequest request; + m_connector = service_manager::Connector::Create(&request); + m_ioThreadContext->BindConnector(std::move(request)); +} + +std::unique_ptr<service_manager::Service> ServiceQt::CreateServiceQtWrapper() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + return std::make_unique<service_manager::ForwardingService>(m_ioThreadContext.get()); +} diff --git a/src/core/service/service_qt.h b/src/core/service/service_qt.h new file mode 100644 index 000000000..4aa0a3996 --- /dev/null +++ b/src/core/service/service_qt.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 SERVICE_QT_H +#define SERVICE_QT_H + +#include "base/no_destructor.h" +#include "services/service_manager/embedder/embedded_service_info.h" + +namespace service_manager { +class Connector; +class Service; +} // namespace service_manager + +class ServiceQt { +public: + static ServiceQt *GetInstance(); + + void InitConnector(); + service_manager::EmbeddedServiceInfo::ServiceFactory CreateServiceQtFactory(); + service_manager::Connector *connector() { return m_connector.get(); } + +private: + friend class base::NoDestructor<ServiceQt>; + class IOThreadContext; + + ServiceQt(); + ~ServiceQt(); + + std::unique_ptr<service_manager::Service> CreateServiceQtWrapper(); + + const std::unique_ptr<IOThreadContext> m_ioThreadContext; + + std::unique_ptr<service_manager::Connector> m_connector; + + DISALLOW_COPY_AND_ASSIGN(ServiceQt); +}; + +#endif // SERVICE_QT_H diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index 2a9746660..4aff2cff6 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -52,6 +52,7 @@ QImage toQImage(const SkBitmap &bitmap) switch (bitmap.colorType()) { case kUnknown_SkColorType: case kRGBA_F16_SkColorType: + case kRGBA_F32_SkColorType: qWarning("Unknown or unsupported skia image format"); break; case kAlpha_8_SkColorType: diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 023bed21e..b9e210c22 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -83,7 +83,7 @@ inline QString toQt(const base::string16 &string) #endif } -inline QString toQt(const std::string &string) +inline QString toQString(const std::string &string) { return QString::fromStdString(string); } @@ -93,6 +93,12 @@ inline QByteArray toQByteArray(const std::string &string) return QByteArray::fromStdString(string); } +// ### should probably be toQByteArray +inline QString toQt(const std::string &string) +{ + return toQString(string); +} + inline base::string16 toString16(const QString &qString) { #if defined(OS_WIN) @@ -109,12 +115,15 @@ inline base::NullableString16 toNullableString16(const QString &qString) inline QUrl toQt(const GURL &url) { - return QUrl(QString::fromStdString(url.spec())); + if (url.is_valid()) + return QUrl::fromEncoded(toQByteArray(url.spec())); + + return QUrl(toQString(url.possibly_invalid_spec())); } inline GURL toGurl(const QUrl& url) { - return GURL(url.toString().toStdString()); + return GURL(url.toEncoded().toStdString()); } inline QPoint toQt(const gfx::Point &point) @@ -265,7 +274,7 @@ inline std::vector<T> toVector(const QStringList &fileList) { std::vector<T> selectedFiles; selectedFiles.reserve(fileList.size()); - Q_FOREACH (const QString &file, fileList) + for (const QString &file : fileList) selectedFiles.push_back(fileListingHelper<T>(file)); return selectedFiles; } diff --git a/src/core/user_script.h b/src/core/user_script.h index 93cde9aa6..5ad53fdc1 100644 --- a/src/core/user_script.h +++ b/src/core/user_script.h @@ -37,12 +37,22 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef USER_SCRIPT_H #define USER_SCRIPT_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" -#include <QtCore/QAtomicInt> #include <QtCore/QScopedPointer> #include <QtCore/QSharedData> #include <QtCore/QString> @@ -53,7 +63,7 @@ namespace QtWebEngineCore { class UserResourceControllerHost; -class QWEBENGINE_EXPORT UserScript : public QSharedData { +class QWEBENGINECORE_PRIVATE_EXPORT UserScript : public QSharedData { public: enum InjectionPoint { AfterLoad, diff --git a/src/core/visited_links_manager_qt.cpp b/src/core/visited_links_manager_qt.cpp index 5e9a89338..ac27446b8 100644 --- a/src/core/visited_links_manager_qt.cpp +++ b/src/core/visited_links_manager_qt.cpp @@ -39,9 +39,9 @@ #include "visited_links_manager_qt.h" -#include "browser_context_adapter.h" -#include "browser_context_qt.h" +#include "profile_adapter.h" #include "content_browser_client_qt.h" +#include "profile_qt.h" #include "type_conversion.h" #include <base/files/file_util.h> @@ -106,14 +106,14 @@ static void ensureDirectoryExists(const base::FilePath &path) errorstr.c_str()); } -VisitedLinksManagerQt::VisitedLinksManagerQt(BrowserContextAdapter *adapter) +VisitedLinksManagerQt::VisitedLinksManagerQt(ProfileAdapter *adapter) : m_delegate(new VisitedLinkDelegateQt) { - Q_ASSERT(adapter && adapter->browserContext()); - BrowserContextQt *browserContext = adapter->browserContext(); + Q_ASSERT(adapter && adapter->profile()); + ProfileQt *profile = adapter->profile(); if (adapter->persistVisitedLinks()) - ensureDirectoryExists(browserContext->GetPath()); - m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(browserContext, m_delegate.data(), adapter->persistVisitedLinks())); + ensureDirectoryExists(profile->GetPath()); + m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(profile, m_delegate.data(), adapter->persistVisitedLinks())); m_visitedLinkMaster->Init(); } diff --git a/src/core/visited_links_manager_qt.h b/src/core/visited_links_manager_qt.h index 30265e033..8d9a7495b 100644 --- a/src/core/visited_links_manager_qt.h +++ b/src/core/visited_links_manager_qt.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef VISITED_LINKS_MANAGER_QT_H #define VISITED_LINKS_MANAGER_QT_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QList> #include <QScopedPointer> @@ -56,14 +67,14 @@ class GURL; namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class VisitedLinkDelegateQt; -class QWEBENGINE_EXPORT VisitedLinksManagerQt { +class QWEBENGINECORE_PRIVATE_EXPORT VisitedLinksManagerQt { public: virtual~VisitedLinksManagerQt(); - VisitedLinksManagerQt(BrowserContextAdapter*); + VisitedLinksManagerQt(ProfileAdapter *profileAdapter); void deleteAllVisitedLinkData(); void deleteVisitedLinkDataForUrls(const QList<QUrl> &); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 57b2039ed..21540f5da 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -42,19 +42,20 @@ // found in the LICENSE.Chromium file. #include "web_contents_adapter.h" -#include "web_contents_adapter_p.h" #include "browser_accessibility_qt.h" -#include "browser_context_adapter.h" -#include "browser_context_adapter_client.h" -#include "browser_context_qt.h" +#include "profile_adapter_client.h" +#include "profile_adapter.h" #include "devtools_frontend_qt.h" #include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" +#if QT_CONFIG(webengine_printing_and_pdf) #include "printing/print_view_manager_qt.h" +#endif +#include "profile_qt.h" #include "qwebenginecallback_p.h" -#include "renderer_host/web_channel_ipc_transport_host.h" #include "render_view_observer_host_qt.h" +#include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "web_contents_view_qt.h" #include "web_engine_context.h" @@ -67,7 +68,8 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/devtools_agent_host.h" -#include <content/public/browser/download_manager.h> +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_request_utils.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" @@ -81,12 +83,18 @@ #include "content/public/common/url_constants.h" #include "content/public/common/web_preferences.h" #include "content/public/common/webrtc_ip_handling_policy.h" -#include "third_party/WebKit/public/web/WebFindOptions.h" -#include "printing/features/features.h" +#include "third_party/blink/public/web/web_find_options.h" +#include "third_party/blink/public/web/web_media_player_action.h" +#include "printing/buildflags/buildflags.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/font_render_params.h" +#if QT_CONFIG(webengine_webchannel) +#include "renderer_host/web_channel_ipc_transport_host.h" +#include <QtWebChannel/QWebChannel> +#endif + #include <QDir> #include <QGuiApplication> #include <QPageLayout> @@ -100,7 +108,6 @@ #include <QtGui/qaccessible.h> #include <QtGui/qdrag.h> #include <QtGui/qpixmap.h> -#include <QtWebChannel/QWebChannel> namespace QtWebEngineCore { @@ -200,7 +207,7 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 adapterClient->didRunJavaScript(requestId, fromJSValue(result)); } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient, int requestId, const std::vector<char>& result) @@ -217,12 +224,13 @@ static void callbackOnPdfSavingFinished(WebContentsAdapterClient *adapterClient, } #endif -static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) +static std::unique_ptr<content::WebContents> createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { content::WebContents::CreateParams create_params(browserContext, NULL); create_params.routing_id = MSG_ROUTING_NONE; create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); create_params.context = reinterpret_cast<gfx::NativeView>(adapterClient); + create_params.initially_hidden = true; return content::WebContents::Create(create_params); } @@ -317,7 +325,8 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, false, // The extra headers are not sync'ed across sessions. std::string(), - browserContext); + browserContext, + nullptr); entry->SetTitle(toString16(title)); entry->SetPageState(content::PageState::CreateFromEncodedData(std::string(pageState.data(), pageState.size()))); @@ -354,34 +363,17 @@ class LoadRecursionGuard { }; } // Anonymous namespace -WebContentsAdapterPrivate::WebContentsAdapterPrivate() - // This has to be the first thing we create, and the last we destroy. - : engineContext(WebEngineContext::current()) - , webChannel(0) - , webChannelWorld(0) - , adapterClient(0) - , nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) - , lastFindRequestId(0) - , currentDropAction(blink::kWebDragOperationNone) - , devToolsFrontend(nullptr) -{ -} - -WebContentsAdapterPrivate::~WebContentsAdapterPrivate() -{ -} - QSharedPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient) { int currentIndex; std::vector<std::unique_ptr<content::NavigationEntry>> entries; - deserializeNavigationHistory(input, ¤tIndex, &entries, adapterClient->browserContextAdapter()->browserContext()); + deserializeNavigationHistory(input, ¤tIndex, &entries, adapterClient->profileAdapter()->profile()); if (currentIndex == -1) return QSharedPointer<WebContentsAdapter>(); // Unlike WebCore, Chromium only supports Restoring to a new WebContents instance. - content::WebContents* newWebContents = createBlankWebContents(adapterClient, adapterClient->browserContextAdapter()->browserContext()); + std::unique_ptr<content::WebContents> newWebContents = createBlankWebContents(adapterClient, adapterClient->profileAdapter()->profile()); content::NavigationController &controller = newWebContents->GetController(); controller.Restore(currentIndex, content::RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries); @@ -396,33 +388,56 @@ QSharedPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavig content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(id, *file); } - return QSharedPointer<WebContentsAdapter>::create(newWebContents); + return QSharedPointer<WebContentsAdapter>::create(std::move(newWebContents)); +} + +WebContentsAdapter::WebContentsAdapter() + : m_profileAdapter(nullptr) + , m_webContents(nullptr) +#if QT_CONFIG(webengine_webchannel) + , m_webChannel(nullptr) + , m_webChannelWorld(0) +#endif + , m_adapterClient(nullptr) + , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) + , m_lastFindRequestId(0) + , m_currentDropAction(blink::kWebDragOperationNone) + , m_devToolsFrontend(nullptr) +{ + // This has to be the first thing we create, and the last we destroy. + WebEngineContext::current(); } -WebContentsAdapter::WebContentsAdapter(content::WebContents *webContents) - : d_ptr(new WebContentsAdapterPrivate) +WebContentsAdapter::WebContentsAdapter(std::unique_ptr<content::WebContents> webContents) + : m_profileAdapter(nullptr) + , m_webContents(std::move(webContents)) +#if QT_CONFIG(webengine_webchannel) + , m_webChannel(nullptr) + , m_webChannelWorld(0) +#endif + , m_adapterClient(nullptr) + , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) + , m_lastFindRequestId(0) + , m_currentDropAction(blink::kWebDragOperationNone) + , m_devToolsFrontend(nullptr) { - Q_D(WebContentsAdapter); - d->webContents.reset(webContents); + // This has to be the first thing we create, and the last we destroy. + WebEngineContext::current(); } WebContentsAdapter::~WebContentsAdapter() { - Q_D(WebContentsAdapter); - if (d->devToolsFrontend) + if (m_devToolsFrontend) closeDevToolsFrontend(); - Q_ASSERT(!d->devToolsFrontend); + Q_ASSERT(!m_devToolsFrontend); } void WebContentsAdapter::setClient(WebContentsAdapterClient *adapterClient) { - Q_D(WebContentsAdapter); Q_ASSERT(!isInitialized()); - d->adapterClient = adapterClient; - // We keep a reference to browserContextAdapter to keep it alive as long as we use it. - // This is needed in case the QML WebEngineProfile is garbage collected before the WebEnginePage. - d->browserContextAdapter = adapterClient->browserContextAdapter(); - Q_ASSERT(d->browserContextAdapter); + m_adapterClient = adapterClient; + m_profileAdapter = adapterClient->profileAdapter(); + Q_ASSERT(m_profileAdapter); // This might replace any adapter that has been initialized with this WebEngineSettings. adapterClient->webEngineSettings()->setWebContentsAdapter(this); @@ -430,37 +445,36 @@ void WebContentsAdapter::setClient(WebContentsAdapterClient *adapterClient) bool WebContentsAdapter::isInitialized() const { - Q_D(const WebContentsAdapter); - return bool(d->webContentsDelegate); + return (bool)m_webContentsDelegate; } void WebContentsAdapter::initialize(content::SiteInstance *site) { - Q_D(WebContentsAdapter); - Q_ASSERT(d->adapterClient); + Q_ASSERT(m_adapterClient); Q_ASSERT(!isInitialized()); // Create our own if a WebContents wasn't provided at construction. - if (!d->webContents) { - content::WebContents::CreateParams create_params(d->browserContextAdapter->browserContext(), site); + if (!m_webContents) { + content::WebContents::CreateParams create_params(m_profileAdapter->profile(), site); create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); - create_params.context = reinterpret_cast<gfx::NativeView>(d->adapterClient); - d->webContents.reset(content::WebContents::Create(create_params)); + create_params.context = reinterpret_cast<gfx::NativeView>(m_adapterClient); + create_params.initially_hidden = true; + m_webContents = content::WebContents::Create(create_params); } - content::RendererPreferences* rendererPrefs = d->webContents->GetMutableRendererPrefs(); + content::RendererPreferences* rendererPrefs = m_webContents->GetMutableRendererPrefs(); rendererPrefs->use_custom_colors = true; // Qt returns a flash time (the whole cycle) in ms, chromium expects just the interval in seconds const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); rendererPrefs->caret_blink_interval = base::TimeDelta::FromMillisecondsD(0.5 * static_cast<double>(qtCursorFlashTime)); - rendererPrefs->user_agent_override = d->browserContextAdapter->httpUserAgent().toStdString(); - rendererPrefs->accept_languages = d->browserContextAdapter->httpAcceptLanguageWithoutQualities().toStdString(); -#if BUILDFLAG(ENABLE_WEBRTC) + rendererPrefs->user_agent_override = m_profileAdapter->httpUserAgent().toStdString(); + rendererPrefs->accept_languages = m_profileAdapter->httpAcceptLanguageWithoutQualities().toStdString(); +#if QT_CONFIG(webengine_webrtc) base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess(); if (commandLine->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) rendererPrefs->webrtc_ip_handling_policy = commandLine->GetSwitchValueASCII(switches::kForceWebRtcIPHandlingPolicy); else - rendererPrefs->webrtc_ip_handling_policy = d->adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) + rendererPrefs->webrtc_ip_handling_policy = m_adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly : content::kWebRTCIPHandlingDefault; #endif @@ -473,89 +487,78 @@ void WebContentsAdapter::initialize(content::SiteInstance *site) rendererPrefs->use_autohinter = params.autohinter; rendererPrefs->use_bitmaps = params.use_bitmaps; rendererPrefs->subpixel_rendering = params.subpixel_rendering; - d->webContents->GetRenderViewHost()->SyncRendererPrefs(); + m_webContents->GetRenderViewHost()->SyncRendererPrefs(); // Create and attach observers to the WebContents. - d->webContentsDelegate.reset(new WebContentsDelegateQt(d->webContents.get(), d->adapterClient)); - d->renderViewObserverHost.reset(new RenderViewObserverHostQt(d->webContents.get(), d->adapterClient)); + m_webContentsDelegate.reset(new WebContentsDelegateQt(m_webContents.get(), m_adapterClient)); + m_renderViewObserverHost.reset(new RenderViewObserverHostQt(m_webContents.get(), m_adapterClient)); // Let the WebContent's view know about the WebContentsAdapterClient. - WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(d->webContents.get())->GetView()); - contentsView->initialize(d->adapterClient); + WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(m_webContents.get())->GetView()); + contentsView->initialize(m_adapterClient); // This should only be necessary after having restored the history to a new WebContentsAdapter. - d->webContents->GetController().LoadIfNecessary(); + m_webContents->GetController().LoadIfNecessary(); -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) PrintViewManagerQt::CreateForWebContents(webContents()); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif // Create an instance of WebEngineVisitedLinksManager to catch the first // content::NOTIFICATION_RENDERER_PROCESS_CREATED event. This event will // force to initialize visited links in VisitedLinkSlave. // It must be done before creating a RenderView. - d->browserContextAdapter->visitedLinksManager(); + m_profileAdapter->visitedLinksManager(); // Create a RenderView with the initial empty document - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) - static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), content::FrameReplicationState()); + static_cast<content::WebContentsImpl*>(m_webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), content::FrameReplicationState()); - d->adapterClient->initializationFinished(); -} + m_webContentsDelegate->RenderViewHostChanged(nullptr, rvh); -void WebContentsAdapter::reattachRWHV() -{ - Q_D(WebContentsAdapter); - CHECK_INITIALIZED(); - if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) - rwhv->InitAsChild(0); + m_adapterClient->initializationFinished(); } bool WebContentsAdapter::canGoBack() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(false); - return d->webContents->GetController().CanGoBack(); + return m_webContents->GetController().CanGoBack(); } bool WebContentsAdapter::canGoForward() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(false); - return d->webContents->GetController().CanGoForward(); + return m_webContents->GetController().CanGoForward(); } void WebContentsAdapter::stop() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - content::NavigationController& controller = d->webContents->GetController(); + content::NavigationController& controller = m_webContents->GetController(); int index = controller.GetPendingEntryIndex(); if (index != -1) controller.RemoveEntryAtIndex(index); - d->webContents->Stop(); + m_webContents->Stop(); focusIfNecessary(); } void WebContentsAdapter::reload() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); - d->webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + m_webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); focusIfNecessary(); } void WebContentsAdapter::reloadAndBypassCache() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); - d->webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + m_webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); focusIfNecessary(); } @@ -573,16 +576,14 @@ void WebContentsAdapter::load(const QUrl &url) void WebContentsAdapter::load(const QWebEngineHttpRequest &request) { - Q_D(WebContentsAdapter); - GURL gurl = toGurl(request.url()); if (!isInitialized()) { scoped_refptr<content::SiteInstance> site = - content::SiteInstance::CreateForURL(d->browserContextAdapter->browserContext(), gurl); + content::SiteInstance::CreateForURL(m_profileAdapter->profile(), gurl); initialize(site.get()); } - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); // The situation can occur when relying on the editingFinished signal in QML to set the url // of the WebView. @@ -623,7 +624,7 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) 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, + m_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")); @@ -652,30 +653,28 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) } } - auto navigate = [this, params]() { - Q_D(WebContentsAdapter); - webContents()->GetController().LoadURLWithParams(params); + auto navigate = [](WebContentsAdapter *adapter, const content::NavigationController::LoadURLParams ¶ms) { + adapter->webContents()->GetController().LoadURLWithParams(params); // Follow chrome::Navigate and invalidate the URL immediately. - d->webContentsDelegate->NavigationStateChanged(webContents(), content::INVALIDATE_TYPE_URL); - focusIfNecessary(); + adapter->m_webContentsDelegate->NavigationStateChanged(adapter->webContents(), content::INVALIDATE_TYPE_URL); + adapter->focusIfNecessary(); }; if (resizeNeeded) { // Schedule navigation on the event loop. - QTimer::singleShot(0, navigate); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, base::BindOnce(navigate, this, std::move(params))); } else { - navigate(); + navigate(this, params); } } void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) { - Q_D(WebContentsAdapter); - if (!isInitialized()) loadDefault(); - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); QByteArray encodedData = data.toPercentEncoding(); std::string urlString; @@ -687,7 +686,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT GURL dataUrlToLoad(urlString); if (dataUrlToLoad.spec().size() > url::kMaxURLChars) { - d->adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED); + m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED); return; } content::NavigationController::LoadURLParams params((dataUrlToLoad)); @@ -697,32 +696,29 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.can_load_local_resources = true; params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API); params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; - d->webContents->GetController().LoadURLWithParams(params); + m_webContents->GetController().LoadURLWithParams(params); focusIfNecessary(); - d->webContents->CollapseSelection(); + m_webContents->CollapseSelection(); } void WebContentsAdapter::save(const QString &filePath, int savePageFormat) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat)); - d->webContents->OnSavePage(); + m_webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat)); + m_webContents->OnSavePage(); } QUrl WebContentsAdapter::activeUrl() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - return d->webContentsDelegate->url(); + return m_webContentsDelegate->url(); } QUrl WebContentsAdapter::requestedUrl() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); - content::NavigationEntry* pendingEntry = d->webContents->GetController().GetPendingEntry(); + content::NavigationEntry* entry = m_webContents->GetController().GetVisibleEntry(); + content::NavigationEntry* pendingEntry = m_webContents->GetController().GetPendingEntry(); if (entry) { if (!entry->GetOriginalRequestURL().is_empty()) @@ -736,9 +732,8 @@ QUrl WebContentsAdapter::requestedUrl() const QUrl WebContentsAdapter::iconUrl() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - if (content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry()) { + if (content::NavigationEntry* entry = m_webContents->GetController().GetVisibleEntry()) { content::FaviconStatus favicon = entry->GetFavicon(); if (favicon.valid) return toQt(favicon.url); @@ -748,152 +743,132 @@ QUrl WebContentsAdapter::iconUrl() const QString WebContentsAdapter::pageTitle() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QString()); - return d->webContentsDelegate->title(); + return m_webContentsDelegate->title(); } QString WebContentsAdapter::selectedText() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QString()); - if (auto *rwhv = d->webContents->GetRenderWidgetHostView()) + if (auto *rwhv = m_webContents->GetRenderWidgetHostView()) return toQt(rwhv->GetSelectedText()); return QString(); } void WebContentsAdapter::undo() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->Undo(); + m_webContents->Undo(); } void WebContentsAdapter::redo() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->Redo(); + m_webContents->Redo(); } void WebContentsAdapter::cut() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->Cut(); + m_webContents->Cut(); } void WebContentsAdapter::copy() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->Copy(); + m_webContents->Copy(); } void WebContentsAdapter::paste() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->Paste(); + m_webContents->Paste(); } void WebContentsAdapter::pasteAndMatchStyle() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->PasteAndMatchStyle(); + m_webContents->PasteAndMatchStyle(); } void WebContentsAdapter::selectAll() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->SelectAll(); + m_webContents->SelectAll(); } void WebContentsAdapter::requestClose() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->DispatchBeforeUnload(); + m_webContents->DispatchBeforeUnload(); } void WebContentsAdapter::unselect() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->CollapseSelection(); + m_webContents->CollapseSelection(); } void WebContentsAdapter::navigateToIndex(int offset) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); - d->webContents->GetController().GoToIndex(offset); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + m_webContents->GetController().GoToIndex(offset); focusIfNecessary(); } void WebContentsAdapter::navigateToOffset(int offset) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); - d->webContents->GetController().GoToOffset(offset); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost()); + m_webContents->GetController().GoToOffset(offset); focusIfNecessary(); } int WebContentsAdapter::navigationEntryCount() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - return d->webContents->GetController().GetEntryCount(); + return m_webContents->GetController().GetEntryCount(); } int WebContentsAdapter::currentNavigationEntryIndex() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - return d->webContents->GetController().GetCurrentEntryIndex(); + return m_webContents->GetController().GetCurrentEntryIndex(); } QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetOriginalRequestURL()) : QUrl(); } QUrl WebContentsAdapter::getNavigationEntryUrl(int index) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetURL()) : QUrl(); } QString WebContentsAdapter::getNavigationEntryTitle(int index) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(QString()); - content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetTitle()) : QString(); } QDateTime WebContentsAdapter::getNavigationEntryTimestamp(int index) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(QDateTime()); - content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetTimestamp()) : QDateTime(); } QUrl WebContentsAdapter::getNavigationEntryIconUrl(int index) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(QUrl()); - content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index); if (!entry) return QUrl(); content::FaviconStatus favicon = entry->GetFavicon(); @@ -902,61 +877,56 @@ QUrl WebContentsAdapter::getNavigationEntryIconUrl(int index) void WebContentsAdapter::clearNavigationHistory() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - if (d->webContents->GetController().CanPruneAllButLastCommitted()) - d->webContents->GetController().PruneAllButLastCommitted(); + if (m_webContents->GetController().CanPruneAllButLastCommitted()) + m_webContents->GetController().PruneAllButLastCommitted(); } void WebContentsAdapter::serializeNavigationHistory(QDataStream &output) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - QtWebEngineCore::serializeNavigationHistory(d->webContents->GetController(), output); + QtWebEngineCore::serializeNavigationHistory(m_webContents->GetController(), output); } void WebContentsAdapter::setZoomFactor(qreal factor) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); if (factor < content::kMinimumZoomFactor || factor > content::kMaximumZoomFactor) return; double zoomLevel = content::ZoomFactorToZoomLevel(static_cast<double>(factor)); - content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(d->webContents.get()); + content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get()); if (zoomMap) { - int render_process_id = d->webContents->GetMainFrame()->GetProcess()->GetID(); - int render_view_id = d->webContents->GetRenderViewHost()->GetRoutingID(); + int render_process_id = m_webContents->GetMainFrame()->GetProcess()->GetID(); + int render_view_id = m_webContents->GetRenderViewHost()->GetRoutingID(); zoomMap->SetTemporaryZoomLevel(render_process_id, render_view_id, zoomLevel); } } qreal WebContentsAdapter::currentZoomFactor() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(1); - return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(d->webContents.get())); + return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get())); } -BrowserContextQt* WebContentsAdapter::browserContext() +ProfileQt* WebContentsAdapter::profile() { - Q_D(WebContentsAdapter); - return d->browserContextAdapter ? d->browserContextAdapter->browserContext() : d->webContents ? static_cast<BrowserContextQt*>(d->webContents->GetBrowserContext()) : 0; + return m_profileAdapter ? m_profileAdapter->profile() : m_webContents ? + static_cast<ProfileQt*>(m_webContents->GetBrowserContext()) : nullptr; } -BrowserContextAdapter* WebContentsAdapter::browserContextAdapter() +ProfileAdapter* WebContentsAdapter::profileAdapter() { - Q_D(WebContentsAdapter); - return d->browserContextAdapter ? d->browserContextAdapter.data() : d->webContents ? static_cast<BrowserContextQt*>(d->webContents->GetBrowserContext())->adapter() : 0; + return m_profileAdapter ? m_profileAdapter : m_webContents ? + static_cast<ProfileQt*>(m_webContents->GetBrowserContext())->profileAdapter() : nullptr; } #ifndef QT_NO_ACCESSIBILITY QAccessibleInterface *WebContentsAdapter::browserAccessible() { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(nullptr); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); content::BrowserAccessibilityManager *manager = static_cast<content::RenderFrameHostImpl*>(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager(); if (!manager) // FIXME! @@ -969,93 +939,86 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (worldId == 0) { rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript)); return; } - content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, d->adapterClient, CallbackDirectory::NoCallbackId); + content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, m_adapterClient, CallbackDirectory::NoCallbackId); rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), callback, worldId); } quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); Q_ASSERT(rvh); - content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, d->adapterClient, d->nextRequestId); + content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, m_adapterClient, m_nextRequestId); if (worldId == 0) rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), callback); else rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), callback, worldId); - return d->nextRequestId++; + return m_nextRequestId++; } quint64 WebContentsAdapter::fetchDocumentMarkup() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - d->renderViewObserverHost->fetchDocumentMarkup(d->nextRequestId); - return d->nextRequestId++; + m_renderViewObserverHost->fetchDocumentMarkup(m_nextRequestId); + return m_nextRequestId++; } quint64 WebContentsAdapter::fetchDocumentInnerText() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - d->renderViewObserverHost->fetchDocumentInnerText(d->nextRequestId); - return d->nextRequestId++; + m_renderViewObserverHost->fetchDocumentInnerText(m_nextRequestId); + return m_nextRequestId++; } quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitively, bool findBackward) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(0); - if (d->lastFindRequestId > d->webContentsDelegate->lastReceivedFindReply()) { + if (m_lastFindRequestId > m_webContentsDelegate->lastReceivedFindReply()) { // There are cases where the render process will overwrite a previous request // with the new search and we'll have a dangling callback, leaving the application // waiting for it forever. // Assume that any unfinished find has been unsuccessful when a new one is started // to cover that case. - d->adapterClient->didFindText(d->lastFindRequestId, 0); + m_adapterClient->didFindText(m_lastFindRequestId, 0); } blink::WebFindOptions options; options.forward = !findBackward; options.match_case = caseSensitively; - options.find_next = subString == d->webContentsDelegate->lastSearchedString(); - d->webContentsDelegate->setLastSearchedString(subString); + options.find_next = subString == m_webContentsDelegate->lastSearchedString(); + m_webContentsDelegate->setLastSearchedString(subString); // Find already allows a request ID as input, but only as an int. // Use the same counter but mod it to MAX_INT, this keeps the same likeliness of request ID clashing. - int shrunkRequestId = d->nextRequestId++ & 0x7fffffff; - d->webContents->Find(shrunkRequestId, toString16(subString), options); - d->lastFindRequestId = shrunkRequestId; + int shrunkRequestId = m_nextRequestId++ & 0x7fffffff; + m_webContents->Find(shrunkRequestId, toString16(subString), options); + m_lastFindRequestId = shrunkRequestId; return shrunkRequestId; } void WebContentsAdapter::stopFinding() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContentsDelegate->setLastSearchedString(QString()); - d->webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); + m_webContentsDelegate->setLastSearchedString(QString()); + m_webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); } void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); + m_webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); // In case of updating preferences during navigation, there might be a pending RVH what will // be active on successful navigation. - content::RenderFrameHost *pendingRFH = (static_cast<content::WebContentsImpl*>(d->webContents.get()))->GetPendingMainFrame(); + content::RenderFrameHost *pendingRFH = (static_cast<content::WebContentsImpl*>(m_webContents.get()))->GetPendingMainFrame(); if (pendingRFH) { content::RenderViewHost *pendingRVH = pendingRFH->GetRenderViewHost(); Q_ASSERT(pendingRVH); @@ -1067,11 +1030,10 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN const QUrl &referrerUrl, ReferrerPolicy referrerPolicy) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - content::BrowserContext *bctx = webContents()->GetBrowserContext(); + content::BrowserContext *bctx = m_webContents->GetBrowserContext(); content::DownloadManager *dlm = content::BrowserContext::GetDownloadManager(bctx); - DownloadManagerDelegateQt *dlmd = d->browserContextAdapter->downloadManagerDelegate(); + DownloadManagerDelegateQt *dlmd = m_profileAdapter->downloadManagerDelegate(); if (!dlm) return; @@ -1097,47 +1059,45 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN "It's possible not to use this feature." })"); GURL gurl = toGurl(url); - std::unique_ptr<content::DownloadUrlParameters> params( - content::DownloadUrlParameters::CreateForWebContentsMainFrame(webContents(), gurl, traffic_annotation)); + std::unique_ptr<download::DownloadUrlParameters> params( + content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(webContents(), gurl, traffic_annotation)); params->set_suggested_name(toString16(suggestedFileName)); // referrer logic based on chrome/browser/renderer_context_menu/render_view_context_menu.cc: - params->set_referrer( - content::Referrer::SanitizeForRequest( - gurl, - content::Referrer(toGurl(referrerUrl).GetAsReferrer(), - static_cast<blink::WebReferrerPolicy>(referrerPolicy)))); + content::Referrer referrer = content::Referrer::SanitizeForRequest( + gurl, + content::Referrer(toGurl(referrerUrl).GetAsReferrer(), + static_cast<blink::WebReferrerPolicy>(referrerPolicy))); + + params->set_referrer(referrer.url); + params->set_referrer_policy(content::Referrer::ReferrerPolicyForUrlRequest(referrer.policy)); dlm->DownloadUrl(std::move(params)); } bool WebContentsAdapter::isAudioMuted() const { - const Q_D(WebContentsAdapter); CHECK_INITIALIZED(false); - return d->webContents->IsAudioMuted(); + return m_webContents->IsAudioMuted(); } void WebContentsAdapter::setAudioMuted(bool muted) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->SetAudioMuted(muted); + m_webContents->SetAudioMuted(muted); } bool WebContentsAdapter::recentlyAudible() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(false); - return d->webContents->WasRecentlyAudible(); + return m_webContents->IsCurrentlyAudible(); } void WebContentsAdapter::copyImageAt(const QPoint &location) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y()); + m_webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y()); } ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerNoAction, blink::WebMediaPlayerAction::kUnknown) @@ -1148,241 +1108,222 @@ ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerControls, blink::WebMediaPlay void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); blink::WebMediaPlayerAction blinkAction((blink::WebMediaPlayerAction::Type)action, enable); - d->webContents->GetRenderViewHost()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction); + m_webContents->GetRenderViewHost()->GetMainFrame()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction); } void WebContentsAdapter::inspectElementAt(const QPoint &location) { - Q_D(WebContentsAdapter); Q_ASSERT(isInitialized()); - if (d->devToolsFrontend) { - d->devToolsFrontend->InspectElementAt(location.x(), location.y()); + if (m_devToolsFrontend) { + m_devToolsFrontend->InspectElementAt(location.x(), location.y()); return; } - if (content::DevToolsAgentHost::HasFor(d->webContents.get())) - content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->InspectElement(nullptr, location.x(), location.y()); + if (content::DevToolsAgentHost::HasFor(m_webContents.get())) + content::DevToolsAgentHost::GetOrCreateFor(m_webContents.get())->InspectElement( + m_webContents->GetFocusedFrame(), location.x(), location.y()); } bool WebContentsAdapter::hasInspector() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(false); - if (d->devToolsFrontend) + if (m_devToolsFrontend) return true; - if (content::DevToolsAgentHost::HasFor(d->webContents.get())) - return content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->IsAttached(); + if (content::DevToolsAgentHost::HasFor(m_webContents.get())) + return content::DevToolsAgentHost::GetOrCreateFor(m_webContents.get())->IsAttached(); return false; } void WebContentsAdapter::openDevToolsFrontend(QSharedPointer<WebContentsAdapter> frontendAdapter) { - Q_D(WebContentsAdapter); Q_ASSERT(isInitialized()); - if (d->devToolsFrontend && frontendAdapter->webContents() && - d->devToolsFrontend->frontendDelegate() == frontendAdapter->webContents()->GetDelegate()) + if (m_devToolsFrontend && frontendAdapter->webContents() && + m_devToolsFrontend->frontendDelegate() == frontendAdapter->webContents()->GetDelegate()) return; - if (d->devToolsFrontend) { - d->devToolsFrontend->DisconnectFromTarget(); - d->devToolsFrontend->Close(); + if (m_devToolsFrontend) { + m_devToolsFrontend->DisconnectFromTarget(); + m_devToolsFrontend->Close(); } - d->devToolsFrontend = DevToolsFrontendQt::Show(frontendAdapter, d->webContents.get()); + m_devToolsFrontend = DevToolsFrontendQt::Show(frontendAdapter, m_webContents.get()); } void WebContentsAdapter::closeDevToolsFrontend() { - Q_D(WebContentsAdapter); - if (d->devToolsFrontend) { - d->devToolsFrontend->DisconnectFromTarget(); - d->devToolsFrontend->Close(); + if (m_devToolsFrontend) { + m_devToolsFrontend->DisconnectFromTarget(); + m_devToolsFrontend->Close(); } } void WebContentsAdapter::devToolsFrontendDestroyed(DevToolsFrontendQt *frontend) { - Q_D(WebContentsAdapter); - Q_ASSERT(frontend == d->devToolsFrontend); + Q_ASSERT(frontend == m_devToolsFrontend); Q_UNUSED(frontend); - d->devToolsFrontend = nullptr; + m_devToolsFrontend = nullptr; } void WebContentsAdapter::exitFullScreen() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->ExitFullscreen(false); + m_webContents->ExitFullscreen(false); } void WebContentsAdapter::changedFullScreen() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->NotifyFullscreenChanged(false); + m_webContents->NotifyFullscreenChanged(false); } void WebContentsAdapter::wasShown() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->WasShown(); + m_webContents->WasShown(); } void WebContentsAdapter::wasHidden() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->WasHidden(); + m_webContents->WasHidden(); } void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString &filePath) { -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - Q_D(WebContentsAdapter); +#if QT_CONFIG(webengine_printing_and_pdf) CHECK_INITIALIZED(); PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished, - d->adapterClient, + m_adapterClient, filePath); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFFileWithCallback(pageLayout, + PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFFileWithCallback(pageLayout, true, filePath, callback); -#endif // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif // QT_CONFIG(webengine_printing_and_pdf) } quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout, bool colorMode, bool useCustomMargins) { -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - Q_D(WebContentsAdapter); +#if QT_CONFIG(webengine_printing_and_pdf) CHECK_INITIALIZED(0); PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, - d->adapterClient, - d->nextRequestId); - PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, + m_adapterClient, + m_nextRequestId); + PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFWithCallback(pageLayout, colorMode, useCustomMargins, callback); - return d->nextRequestId++; + return m_nextRequestId++; #else Q_UNUSED(pageLayout); Q_UNUSED(colorMode); return 0; -#endif // if BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif // QT_CONFIG(webengine_printing_and_pdf) } QPointF WebContentsAdapter::lastScrollOffset() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QPointF()); - if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) - return toQt(rwhv->GetLastScrollOffset()); + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) + return toQt(rwhv->lastScrollOffset()); return QPointF(); } QSizeF WebContentsAdapter::lastContentsSize() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(QSizeF()); - if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) return toQt(rwhv->lastContentsSize()); return QSizeF(); } void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); // Let the permission manager remember the reply. if (flags & WebContentsAdapterClient::MediaAudioCapture) - d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::AudioCapturePermission, true); + m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::AudioCapturePermission, true); if (flags & WebContentsAdapterClient::MediaVideoCapture) - d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::VideoCapturePermission, true); - MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(d->webContents.get(), securityOrigin, flags); + m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::VideoCapturePermission, true); + MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), securityOrigin, flags); } void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::GeolocationPermission, allowed); + m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::GeolocationPermission, allowed); } void WebContentsAdapter::grantMouseLockPermission(bool granted) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); if (granted) { - if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) rwhv->Focus(); else granted = false; } - d->webContents->GotResponseToLockMouseRequest(granted); + m_webContents->GotResponseToLockMouseRequest(granted); } void WebContentsAdapter::dpiScaleChanged() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); content::RenderWidgetHostImpl* impl = NULL; - if (d->webContents->GetRenderViewHost()) - impl = content::RenderWidgetHostImpl::From(d->webContents->GetRenderViewHost()->GetWidget()); + if (m_webContents->GetRenderViewHost()) + impl = content::RenderWidgetHostImpl::From(m_webContents->GetRenderViewHost()->GetWidget()); if (impl) impl->NotifyScreenInfoChanged(); } -void WebContentsAdapter::backgroundColorChanged() +void WebContentsAdapter::setBackgroundColor(const QColor &color) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) - rwhv->SetBackgroundColor(toSk(d->adapterClient->backgroundColor())); + if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView()) + rwhv->SetBackgroundColor(toSk(color)); } content::WebContents *WebContentsAdapter::webContents() const { - Q_D(const WebContentsAdapter); - return d->webContents.get(); + return m_webContents.get(); } +#if QT_CONFIG(webengine_webchannel) QWebChannel *WebContentsAdapter::webChannel() const { - Q_D(const WebContentsAdapter); - return d->webChannel; + return m_webChannel; } void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - if (d->webChannel == channel && d->webChannelWorld == worldId) + if (m_webChannel == channel && m_webChannelWorld == worldId) return; - if (!d->webChannelTransport.get()) - d->webChannelTransport.reset(new WebChannelIPCTransportHost(d->webContents.get(), worldId)); + if (!m_webChannelTransport.get()) + m_webChannelTransport.reset(new WebChannelIPCTransportHost(m_webContents.get(), worldId)); else { - if (d->webChannel != channel) - d->webChannel->disconnectFrom(d->webChannelTransport.get()); - if (d->webChannelWorld != worldId) - d->webChannelTransport->setWorldId(worldId); + if (m_webChannel != channel) + m_webChannel->disconnectFrom(m_webChannelTransport.get()); + if (m_webChannelWorld != worldId) + m_webChannelTransport->setWorldId(worldId); } - d->webChannel = channel; - d->webChannelWorld = worldId; + m_webChannel = channel; + m_webChannelWorld = worldId; if (!channel) { - d->webChannelTransport.reset(); + m_webChannelTransport.reset(); return; } - channel->connectTo(d->webChannelTransport.get()); + channel->connectTo(m_webChannelTransport.get()); } +#endif #if QT_CONFIG(draganddrop) static QMimeData *mimeDataFromDropData(const content::DropData &dropData) @@ -1418,20 +1359,19 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - if (d->currentDropData) + if (m_currentDropData) return; // Clear certain fields of the drop data to not run into DCHECKs // of DropDataToWebDragData in render_view_impl.cc. - d->currentDropData.reset(new content::DropData(dropData)); - d->currentDropData->download_metadata.clear(); - d->currentDropData->file_contents.clear(); - d->currentDropData->file_contents_content_disposition.clear(); + m_currentDropData.reset(new content::DropData(dropData)); + m_currentDropData->download_metadata.clear(); + m_currentDropData->file_contents.clear(); + m_currentDropData->file_contents_content_disposition.clear(); - d->currentDropAction = blink::kWebDragOperationNone; + m_currentDropAction = blink::kWebDragOperationNone; QDrag *drag = new QDrag(dragSource); // will be deleted by Qt's DnD implementation bool dValid = true; QMetaObject::Connection onDestroyed = QObject::connect(dragSource, &QObject::destroyed, [&dValid](){ @@ -1439,7 +1379,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD QDrag::cancel(); }); - QMimeData *mimeData = mimeDataFromDropData(*d->currentDropData); + QMimeData *mimeData = mimeDataFromDropData(*m_currentDropData); if (handleDropDataFileContents(dropData, mimeData)) allowedActions = Qt::MoveAction; @@ -1450,22 +1390,22 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD } { - base::MessageLoop::ScopedNestableTaskAllower allow(base::MessageLoop::current()); + base::MessageLoop::ScopedNestableTaskAllower allow; drag->exec(allowedActions); } QObject::disconnect(onDestroyed); if (dValid) { - if (d->webContents) { - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + if (m_webContents) { + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); if (rvh) { - rvh->GetWidget()->DragSourceEndedAt(gfx::PointF(d->lastDragClientPos.x(), d->lastDragClientPos.y()), - gfx::PointF(d->lastDragScreenPos.x(), d->lastDragScreenPos.y()), - d->currentDropAction); + rvh->GetWidget()->DragSourceEndedAt(gfx::PointF(m_lastDragClientPos.x(), m_lastDragClientPos.y()), + gfx::PointF(m_lastDragScreenPos.x(), m_lastDragScreenPos.y()), + blink::WebDragOperation(m_currentDropAction)); rvh->GetWidget()->DragSourceSystemDragEnded(); } } - d->currentDropData.reset(); + m_currentDropData.reset(); } } @@ -1476,22 +1416,17 @@ bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dro if (dropData.file_contents.empty()) return false; - Q_D(WebContentsAdapter); - if (!d->dndTmpDir) { - d->dndTmpDir.reset(new QTemporaryDir); - if (!d->dndTmpDir->isValid()) { - d->dndTmpDir.reset(); + if (!m_dndTmpDir) { + m_dndTmpDir.reset(new QTemporaryDir); + if (!m_dndTmpDir->isValid()) { + m_dndTmpDir.reset(); return false; } } const auto maybeFilename = dropData.GetSafeFilenameForImageFileContents(); const QString fileName = maybeFilename ? toQt(maybeFilename->AsUTF16Unsafe()) : QString(); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) - const QString &filePath = d->dndTmpDir->filePath(fileName); -#else - const QString &filePath = d->dndTmpDir->path() + QLatin1Char('/') + fileName; -#endif + const QString &filePath = m_dndTmpDir->filePath(fileName); QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { qWarning("Cannot write temporary file %s.", qUtf8Printable(filePath)); @@ -1507,7 +1442,8 @@ bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dro static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeData *mimeData) { Q_ASSERT(dropData->filenames.empty()); - Q_FOREACH (const QUrl &url, mimeData->urls()) { + const QList<QUrl> urls = mimeData->urls(); + for (const QUrl &url : urls) { if (url.isLocalFile()) { ui::FileInfo uifi; uifi.path = toFilePath(url.toLocalFile()); @@ -1565,48 +1501,45 @@ static int toWeb(Qt::KeyboardModifiers modifiers) void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPointF &screenPos) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - if (!d->currentDropData) { + if (!m_currentDropData) { // The drag originated outside the WebEngineView. - d->currentDropData.reset(new content::DropData); - fillDropDataFromMimeData(d->currentDropData.get(), e->mimeData()); + m_currentDropData.reset(new content::DropData); + fillDropDataFromMimeData(m_currentDropData.get(), e->mimeData()); } - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - rvh->GetWidget()->FilterDropData(d->currentDropData.get()); - rvh->GetWidget()->DragTargetDragEnter(*d->currentDropData, toGfx(e->posF()), toGfx(screenPos), + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + rvh->GetWidget()->FilterDropData(m_currentDropData.get()); + rvh->GetWidget()->DragTargetDragEnter(*m_currentDropData, toGfx(e->posF()), toGfx(screenPos), toWeb(e->possibleActions()), toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers())); } Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const QPointF &screenPos) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(Qt::DropAction()); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - d->lastDragClientPos = toGfx(e->posF()); - d->lastDragScreenPos = toGfx(screenPos); - rvh->GetWidget()->DragTargetDragOver(d->lastDragClientPos, d->lastDragScreenPos, toWeb(e->possibleActions()), + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + m_lastDragClientPos = e->posF(); + m_lastDragScreenPos = screenPos; + rvh->GetWidget()->DragTargetDragOver(toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos), toWeb(e->possibleActions()), toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers())); waitForUpdateDragActionCalled(); - return toQt(d->currentDropAction); + return toQt(blink::WebDragOperation(m_currentDropAction)); } void WebContentsAdapter::waitForUpdateDragActionCalled() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); const qint64 timeout = 3000; QElapsedTimer t; t.start(); base::MessagePump::Delegate *delegate = base::MessageLoop::current(); DCHECK(delegate); - d->updateDragActionCalled = false; + m_updateDragActionCalled = false; for (;;) { - while (delegate->DoWork() && !d->updateDragActionCalled) {} - if (d->updateDragActionCalled) + while (delegate->DoWork() && !m_updateDragActionCalled) {} + if (m_updateDragActionCalled) break; if (t.hasExpired(timeout)) { qWarning("WebContentsAdapter::updateDragAction was not called within %d ms.", @@ -1619,59 +1552,54 @@ void WebContentsAdapter::waitForUpdateDragActionCalled() void WebContentsAdapter::updateDragAction(int action) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->updateDragActionCalled = true; - d->currentDropAction = static_cast<blink::WebDragOperation>(action); + m_updateDragActionCalled = true; + m_currentDropAction = static_cast<blink::WebDragOperation>(action); } void WebContentsAdapter::endDragging(QDropEvent *e, const QPointF &screenPos) { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - rvh->GetWidget()->FilterDropData(d->currentDropData.get()); - d->lastDragClientPos = toGfx(e->posF()); - d->lastDragScreenPos = toGfx(screenPos); - rvh->GetWidget()->DragTargetDrop(*d->currentDropData, d->lastDragClientPos, d->lastDragScreenPos, + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + rvh->GetWidget()->FilterDropData(m_currentDropData.get()); + m_lastDragClientPos = e->posF(); + m_lastDragScreenPos = screenPos; + rvh->GetWidget()->DragTargetDrop(*m_currentDropData, toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos), toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers())); - d->currentDropData.reset(); + + m_currentDropData.reset(); } void WebContentsAdapter::leaveDrag() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - rvh->GetWidget()->DragTargetDragLeave(d->lastDragClientPos, d->lastDragScreenPos); - d->currentDropData.reset(); + content::RenderViewHost *rvh = m_webContents->GetRenderViewHost(); + rvh->GetWidget()->DragTargetDragLeave(toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos)); + m_currentDropData.reset(); } #endif // QT_CONFIG(draganddrop) void WebContentsAdapter::replaceMisspelling(const QString &word) { -#if BUILDFLAG(ENABLE_SPELLCHECK) - Q_D(WebContentsAdapter); +#if QT_CONFIG(webengine_spellchecker) CHECK_INITIALIZED(); - d->webContents->ReplaceMisspelling(toString16(word)); + m_webContents->ReplaceMisspelling(toString16(word)); #endif } void WebContentsAdapter::focusIfNecessary() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - const WebEngineSettings *settings = d->adapterClient->webEngineSettings(); + const WebEngineSettings *settings = m_adapterClient->webEngineSettings(); bool focusOnNavigation = settings->testAttribute(WebEngineSettings::FocusOnNavigationEnabled); if (focusOnNavigation) - d->webContents->Focus(); + m_webContents->Focus(); } bool WebContentsAdapter::isFindTextInProgress() const { - Q_D(const WebContentsAdapter); CHECK_INITIALIZED(false); - return d->lastFindRequestId != d->webContentsDelegate->lastReceivedFindReply(); + return m_lastFindRequestId != m_webContentsDelegate->lastReceivedFindReply(); } WebContentsAdapterClient::RenderProcessTerminationStatus @@ -1708,23 +1636,20 @@ WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { FaviconManager *WebContentsAdapter::faviconManager() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(nullptr); - return d->webContentsDelegate->faviconManager(); + return m_webContentsDelegate->faviconManager(); } void WebContentsAdapter::viewSource() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(); - d->webContents->GetMainFrame()->ViewSource(); + m_webContents->GetMainFrame()->ViewSource(); } bool WebContentsAdapter::canViewSource() { - Q_D(WebContentsAdapter); CHECK_INITIALIZED(false); - return d->webContents->GetController().CanViewSource(); + return m_webContents->GetController().CanViewSource(); } ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UnknownDisposition, WindowOpenDisposition::UNKNOWN) diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index d5dbcf122..e8e5359be 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -37,11 +37,23 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef WEB_CONTENTS_ADAPTER_H #define WEB_CONTENTS_ADAPTER_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include "web_contents_adapter_client.h" +#include <memory> #include <QtGui/qtgui-config.h> #include <QtWebEngineCore/qwebenginehttprequest.h> @@ -65,22 +77,25 @@ class QDropEvent; class QMimeData; class QPageLayout; class QString; +class QTemporaryDir; class QWebChannel; QT_END_NAMESPACE namespace QtWebEngineCore { -class BrowserContextQt; class DevToolsFrontendQt; -class MessagePassingInterface; -class WebContentsAdapterPrivate; class FaviconManager; +class MessagePassingInterface; +class ProfileQt; +class RenderViewObserverHostQt; +class WebChannelIPCTransportHost; +class WebEngineContext; -class QWEBENGINE_EXPORT WebContentsAdapter : public QEnableSharedFromThis<WebContentsAdapter> { +class QWEBENGINECORE_PRIVATE_EXPORT WebContentsAdapter : public QEnableSharedFromThis<WebContentsAdapter> { public: static QSharedPointer<WebContentsAdapter> createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient); - // Takes ownership of the WebContents. - WebContentsAdapter(content::WebContents *webContents = 0); + WebContentsAdapter(); + WebContentsAdapter(std::unique_ptr<content::WebContents> webContents); ~WebContentsAdapter(); void setClient(WebContentsAdapterClient *adapterClient); @@ -94,8 +109,6 @@ public: void load(const QWebEngineHttpRequest &request); void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl); - void reattachRWHV(); - bool canGoBack() const; bool canGoForward() const; void stop(); @@ -172,12 +185,14 @@ public: void grantMouseLockPermission(bool granted); void dpiScaleChanged(); - void backgroundColorChanged(); + void setBackgroundColor(const QColor &color); QAccessibleInterface *browserAccessible(); - BrowserContextQt* browserContext(); - BrowserContextAdapter* browserContextAdapter(); + ProfileQt* profile(); + ProfileAdapter* profileAdapter(); +#if QT_CONFIG(webengine_webchannel) QWebChannel *webChannel() const; void setWebChannel(QWebChannel *, uint worldId); +#endif FaviconManager *faviconManager(); QPointF lastScrollOffset() const; @@ -209,11 +224,28 @@ public: private: Q_DISABLE_COPY(WebContentsAdapter) - Q_DECLARE_PRIVATE(WebContentsAdapter) void waitForUpdateDragActionCalled(); bool handleDropDataFileContents(const content::DropData &dropData, QMimeData *mimeData); - QScopedPointer<WebContentsAdapterPrivate> d_ptr; + ProfileAdapter *m_profileAdapter; + std::unique_ptr<content::WebContents> m_webContents; + std::unique_ptr<WebContentsDelegateQt> m_webContentsDelegate; + std::unique_ptr<RenderViewObserverHostQt> m_renderViewObserverHost; +#if QT_CONFIG(webengine_webchannel) + std::unique_ptr<WebChannelIPCTransportHost> m_webChannelTransport; + QWebChannel *m_webChannel; + unsigned int m_webChannelWorld; +#endif + WebContentsAdapterClient *m_adapterClient; + quint64 m_nextRequestId; + int m_lastFindRequestId; + std::unique_ptr<content::DropData> m_currentDropData; + uint m_currentDropAction; + bool m_updateDragActionCalled; + QPointF m_lastDragClientPos; + QPointF m_lastDragScreenPos; + std::unique_ptr<QTemporaryDir> m_dndTmpDir; + DevToolsFrontendQt *m_devToolsFrontend; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 0469867f2..55cbe13dd 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef WEB_CONTENTS_ADAPTER_CLIENT_H #define WEB_CONTENTS_ADAPTER_CLIENT_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QFlags> #include <QRect> @@ -50,6 +61,7 @@ #include <QUrl> QT_FORWARD_DECLARE_CLASS(CertificateErrorController) +QT_FORWARD_DECLARE_CLASS(ClientCertSelectController) QT_FORWARD_DECLARE_CLASS(QKeyEvent) QT_FORWARD_DECLARE_CLASS(QVariant) QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest) @@ -62,7 +74,7 @@ struct DropData; namespace QtWebEngineCore { class AuthenticationDialogController; -class BrowserContextAdapter; +class ProfileAdapter; class ColorChooserController; class FilePickerController; class JavaScriptDialogController; @@ -328,7 +340,7 @@ private: }; -class QWEBENGINE_EXPORT WebContentsAdapterClient { +class QWEBENGINECORE_PRIVATE_EXPORT WebContentsAdapterClient { public: // This must match window_open_disposition_list.h. enum WindowOpenDisposition { @@ -382,6 +394,11 @@ public: KilledTerminationStatus }; + enum ClientType { + QmlClient, + WidgetsClient + }; + enum MediaRequestFlag { MediaNone = 0, MediaAudioCapture = 0x01, @@ -445,16 +462,21 @@ public: virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0; virtual void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) = 0; virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) = 0; + virtual void selectClientCert(const QSharedPointer<ClientCertSelectController> &selectController) = 0; virtual void updateScrollPosition(const QPointF &position) = 0; virtual void updateContentsSize(const QSizeF &size) = 0; + virtual void updateNavigationActions() = 0; virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) = 0; virtual bool supportsDragging() const = 0; virtual bool isEnabled() const = 0; virtual const QObject *holdingQObject() const = 0; virtual void setToolTip(const QString& toolTipText) = 0; + virtual ClientType clientType() = 0; + virtual void printRequested() = 0; + virtual void widgetChanged(RenderWidgetHostViewQtDelegate *newWidget) = 0; - virtual QSharedPointer<BrowserContextAdapter> browserContextAdapter() = 0; + virtual ProfileAdapter *profileAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; }; diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h deleted file mode 100644 index 5b902fc94..000000000 --- a/src/core/web_contents_adapter_p.h +++ /dev/null @@ -1,109 +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 WEB_CONTENTS_ADAPTER_P_H -#define WEB_CONTENTS_ADAPTER_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 "web_contents_adapter.h" - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "ui/gfx/geometry/point_f.h" -#include "third_party/WebKit/public/platform/WebDragOperation.h" - -#include <QScopedPointer> -#include <QSharedPointer> - -QT_FORWARD_DECLARE_CLASS(QTemporaryDir) -QT_FORWARD_DECLARE_CLASS(QWebChannel) - -class WebEngineContext; - -namespace content { -struct DropData; -} - -namespace QtWebEngineCore { - -class BrowserContextAdapter; -class DevToolsFrontendQt; -class RenderViewObserverHostQt; -class WebChannelIPCTransportHost; -class WebContentsAdapterClient; -class WebContentsDelegateQt; -class WebEngineContext; - -class WebContentsAdapterPrivate { -public: - WebContentsAdapterPrivate(); - ~WebContentsAdapterPrivate(); - scoped_refptr<WebEngineContext> engineContext; - QSharedPointer<BrowserContextAdapter> browserContextAdapter; - std::unique_ptr<content::WebContents> webContents; - std::unique_ptr<WebContentsDelegateQt> webContentsDelegate; - std::unique_ptr<RenderViewObserverHostQt> renderViewObserverHost; - std::unique_ptr<WebChannelIPCTransportHost> webChannelTransport; - QWebChannel *webChannel; - unsigned int webChannelWorld; - WebContentsAdapterClient *adapterClient; - quint64 nextRequestId; - int lastFindRequestId; - std::unique_ptr<content::DropData> currentDropData; - blink::WebDragOperation currentDropAction; - bool updateDragActionCalled; - gfx::PointF lastDragClientPos; - gfx::PointF lastDragScreenPos; - std::unique_ptr<QTemporaryDir> dndTmpDir; - DevToolsFrontendQt *devToolsFrontend; -}; - -} // namespace QtWebEngineCore - -#endif // WEB_CONTENTS_ADAPTER_P_H diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index aae7f4a43..4bde93fd3 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -43,22 +43,21 @@ #include "web_contents_delegate_qt.h" -#include "browser_context_adapter.h" -#include "browser_context_qt.h" -#include "color_chooser_qt.h" +#include "profile_adapter.h" #include "color_chooser_controller.h" +#include "color_chooser_qt.h" #include "favicon_manager.h" -#include "favicon_manager_p.h" #include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" #include "net/network_delegate_qt.h" +#include "profile_qt.h" #include "qwebengineregisterprotocolhandlerrequest.h" #include "register_protocol_handler_request_controller_impl.h" #include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "visited_links_manager_qt.h" #include "web_contents_adapter_client.h" -#include "web_contents_adapter_p.h" +#include "web_contents_adapter.h" #include "web_engine_context.h" #include "web_engine_settings.h" @@ -88,7 +87,8 @@ namespace QtWebEngineCore { // Maps the LogSeverity defines in base/logging.h to the web engines message levels. -static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32_t messageLevel) { +static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32_t messageLevel) +{ if (messageLevel < 1) return WebContentsAdapterClient::Info; else if (messageLevel > 1) @@ -100,7 +100,7 @@ static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptCo WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient) : m_viewClient(adapterClient) , m_lastReceivedFindReply(0) - , m_faviconManager(new FaviconManager(new FaviconManagerPrivate(webContents, adapterClient))) + , m_faviconManager(new FaviconManager(webContents, adapterClient)) , m_lastLoadProgress(-1) { webContents->SetDelegate(this); @@ -122,7 +122,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents if (params.disposition != WindowOpenDisposition::CURRENT_TAB) { QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); if (targetAdapter) { - if (targetAdapter->browserContext() != source->GetBrowserContext()) { + if (targetAdapter->profile() != source->GetBrowserContext()) { target_site_instance = nullptr; referrer = content::Referrer(); } @@ -215,14 +215,14 @@ void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, // Make sure to only emit the signal when loading isn't in progress, because it causes multiple // false signals to be emitted. if ((changed_flags & content::INVALIDATE_TYPE_TAB) && !(changed_flags & content::INVALIDATE_TYPE_LOAD)) { - m_viewClient->recentlyAudibleChanged(source->WasRecentlyAudible()); + m_viewClient->recentlyAudibleChanged(source->IsCurrentlyAudible()); } } -void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) +void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) - QSharedPointer<WebContentsAdapter> newAdapter = createWindow(new_contents, disposition, initial_pos, user_gesture); + QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, user_gesture); if (newAdapter && !newAdapter->isInitialized()) newAdapter->loadDefault(); if (was_blocked) @@ -258,11 +258,20 @@ void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_ m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); } +void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *, content::RenderViewHost *newHost) +{ + if (newHost && newHost->GetWidget() && newHost->GetWidget()->GetView()) { + auto rwhv = static_cast<RenderWidgetHostViewQt *>(newHost->GetWidget()->GetView()); + m_viewClient->widgetChanged(rwhv->delegate()); + } +} + void WebContentsDelegateQt::EmitLoadStarted(const QUrl &url, bool isErrorPage) { if (m_lastLoadProgress >= 0 && m_lastLoadProgress < 100) // already running return; m_viewClient->loadStarted(url, isErrorPage); + m_viewClient->updateNavigationActions(); m_viewClient->loadProgressChanged(0); m_lastLoadProgress = 0; } @@ -287,6 +296,16 @@ void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool m_lastLoadProgress = -1; m_viewClient->loadProgressChanged(100); m_viewClient->loadFinished(success, url, isErrorPage, errorCode, errorDescription); + m_viewClient->updateNavigationActions(); +} + +void WebContentsDelegateQt::EmitLoadCommitted() +{ + // Make sure that we don't set the findNext WebFindOptions on a new frame. + m_lastSearchedString = QString(); + + m_viewClient->loadCommitted(); + m_viewClient->updateNavigationActions(); } void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navigation_handle) @@ -295,18 +314,14 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig return; if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) { - BrowserContextAdapter *browserContextAdapter = m_viewClient->browserContextAdapter().data(); + ProfileAdapter *profileAdapter = m_viewClient->profileAdapter(); // VisistedLinksMaster asserts !IsOffTheRecord(). - if (navigation_handle->ShouldUpdateHistory() && browserContextAdapter->trackVisitedLinks()) { + if (navigation_handle->ShouldUpdateHistory() && profileAdapter->trackVisitedLinks()) { for (const GURL &url : navigation_handle->GetRedirectChain()) - browserContextAdapter->visitedLinksManager()->addUrl(url); + profileAdapter->visitedLinksManager()->addUrl(url); } - // Make sure that we don't set the findNext WebFindOptions on a new frame. - m_lastSearchedString = QString(); - - // This is currently used for canGoBack/Forward values, which is flattened across frames. For other purposes we might have to pass is_main_frame. - m_viewClient->loadCommitted(); + EmitLoadCommitted(); } // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below if (navigation_handle->GetNetErrorCode() == net::OK) @@ -325,10 +340,8 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call. - if (navigation_handle->HasCommitted()) { - m_lastSearchedString = QString(); - m_viewClient->loadCommitted(); - } + if (navigation_handle->HasCommitted()) + EmitLoadCommitted(); } } @@ -340,7 +353,7 @@ void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QS void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) { - if (render_frame_host->GetParent()) + if (render_frame_host != web_contents()->GetMainFrame()) return; if (validated_url.spec() == content::kUnreachableWebDataURL) { @@ -376,7 +389,11 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame if (!m_faviconManager->hasCandidate()) m_viewClient->iconChanged(QUrl()); - EmitLoadFinished(true, toQt(validated_url)); + content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry(); + int http_statuscode = 0; + if (entry) + http_statuscode = entry->GetHttpStatusCode(); + EmitLoadFinished(true /* success */ , toQt(validated_url), false /* isErrorPage */, http_statuscode); } void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) @@ -415,7 +432,7 @@ content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogMana return JavaScriptDialogManagerQt::GetInstance(); } -void WebContentsDelegateQt::EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL& origin) +void WebContentsDelegateQt::EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL& origin, const blink::WebFullscreenOptions &) { Q_UNUSED(web_contents); if (!m_viewClient->isFullScreenMode()) @@ -473,14 +490,17 @@ void WebContentsDelegateQt::FindReply(content::WebContents *source, int request_ } } -void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *web_contents, const content::MediaStreamRequest &request, const content::MediaResponseCallback &callback) +void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *web_contents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) { - MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(m_viewClient, web_contents, request, callback); + MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(m_viewClient, web_contents, request, std::move(callback)); } -void WebContentsDelegateQt::MoveContents(content::WebContents *source, const gfx::Rect &pos) +void WebContentsDelegateQt::SetContentsBounds(content::WebContents *source, const gfx::Rect &bounds) { - QRect frameGeometry(toQt(pos)); + if (!source->HasOpener()) // is popup + return; + + QRect frameGeometry(toQt(bounds)); QRect geometry; if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView())) { if (rwhv->delegate() && rwhv->delegate()->window()) @@ -489,20 +509,16 @@ void WebContentsDelegateQt::MoveContents(content::WebContents *source, const gfx m_viewClient->requestGeometryChange(geometry, frameGeometry); } -bool WebContentsDelegateQt::IsPopupOrPanel(const content::WebContents *source) const -{ - return source->HasOpener(); -} - void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const GURL& url) { Q_UNUSED(source) m_viewClient->didUpdateTargetURL(toQt(url)); } -void WebContentsDelegateQt::WasShown() +void WebContentsDelegateQt::OnVisibilityChanged(content::Visibility visibility) { - web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetMainFrame()->GetProcess()->GetID()); + if (visibility != content::Visibility::HIDDEN) + web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetMainFrame()->GetProcess()->GetID()); } void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint() @@ -542,9 +558,9 @@ void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webCont m_viewClient->webEngineSettings()->overrideWebPreferences(webContents, webPreferences); } -QWeakPointer<WebContentsAdapter> WebContentsDelegateQt::createWindow(content::WebContents *new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture) +QWeakPointer<WebContentsAdapter> WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture) { - QSharedPointer<WebContentsAdapter> newAdapter = QSharedPointer<WebContentsAdapter>::create(new_contents); + QSharedPointer<WebContentsAdapter> newAdapter = QSharedPointer<WebContentsAdapter>::create(std::move(new_contents)); m_viewClient->adoptNewWindow(newAdapter, static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), user_gesture, toQt(initial_pos), m_initialTargetUrl); @@ -557,6 +573,11 @@ void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<Certifica m_viewClient->allowCertificateError(errorController); } +void WebContentsDelegateQt::selectClientCert(const QSharedPointer<ClientCertSelectController> &selectController) +{ + m_viewClient->selectClientCert(selectController); +} + void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingOrigin) { m_viewClient->runGeolocationPermissionRequest(requestingOrigin); @@ -594,14 +615,12 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio } if (!navigationAllowedByPolicy || !navigationRequestAccepted) { + QString errorDescription; if (!navigationAllowedByPolicy) - didFailLoad(url, 420, QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy")); + errorDescription = QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy"); else - didFailLoad(url, 420, QStringLiteral("Launching external protocol suppressed by WebContentsAdapterClient::navigationRequested")); - if (settings->testAttribute(WebEngineSettings::ErrorPageEnabled)) { - EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); - m_viewClient->webContentsAdapter()->load(toQt(GURL(content::kUnreachableWebDataURL))); - } + errorDescription = QStringLiteral("Launching external protocol suppressed by WebContentsAdapterClient::navigationRequested"); + didFailLoad(url, net::Error::ERR_ABORTED, errorDescription); } } @@ -618,13 +637,13 @@ void WebContentsDelegateQt::BeforeUnloadFired(const base::TimeTicks &proceed_tim Q_UNUSED(proceed_time); } -bool WebContentsDelegateQt::CheckMediaAccessPermission(content::WebContents *web_contents, const GURL& security_origin, content::MediaStreamType type) +bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, const GURL& security_origin, content::MediaStreamType type) { switch (type) { case content::MEDIA_DEVICE_AUDIO_CAPTURE: - return m_viewClient->browserContextAdapter()->checkPermission(toQt(security_origin), BrowserContextAdapter::AudioCapturePermission); + return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::AudioCapturePermission); case content::MEDIA_DEVICE_VIDEO_CAPTURE: - return m_viewClient->browserContextAdapter()->checkPermission(toQt(security_origin), BrowserContextAdapter::VideoCapturePermission); + return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::VideoCapturePermission); default: LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: " << "Unsupported media stream type checked" << type; diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 2ef87ccd8..9c0f8f484 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -53,12 +53,11 @@ #include <QtCore/qvector.h> QT_FORWARD_DECLARE_CLASS(CertificateErrorController) +QT_FORWARD_DECLARE_CLASS(ClientCertSelectController) namespace content { - class BrowserContext; class ColorChooser; class SiteInstance; - class RenderViewHost; class JavaScriptDialogManager; class WebContents; struct WebPreferences; @@ -104,7 +103,7 @@ public: // WebContentsDelegate overrides content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms) override; void NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) override; - void AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) override; + void AddNewContents(content::WebContents *source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect &initial_pos, bool user_gesture, bool *was_blocked) override; void CloseContents(content::WebContents *source) override; void LoadProgressChanged(content::WebContents* source, double progress) override; void HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) override; @@ -112,37 +111,40 @@ public: void WebContentsCreated(content::WebContents *source_contents, int opener_render_process_id, int opener_render_frame_id, const std::string &frame_name, const GURL &target_url, content::WebContents *new_contents) override; content::JavaScriptDialogManager *GetJavaScriptDialogManager(content::WebContents *source) override; - void EnterFullscreenModeForTab(content::WebContents* web_contents, const GURL& origin) override; + void EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL &origin, const blink::WebFullscreenOptions &) override; void ExitFullscreenModeForTab(content::WebContents*) override; bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) const override; void RunFileChooser(content::RenderFrameHost* render_frame_host, const content::FileChooserParams& params) override; bool DidAddMessageToConsole(content::WebContents* source, int32_t level, const base::string16& message, int32_t line_no, const base::string16& source_id) override; void FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) override; - void RequestMediaAccessPermission(content::WebContents* web_contents, const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback) override; - void MoveContents(content::WebContents *source, const gfx::Rect &pos) override; - bool IsPopupOrPanel(const content::WebContents *source) const override; + void RequestMediaAccessPermission(content::WebContents *web_contents, + const content::MediaStreamRequest &request, + content::MediaResponseCallback callback) override; + void SetContentsBounds(content::WebContents *source, const gfx::Rect &bounds) override; void UpdateTargetURL(content::WebContents* source, const GURL& url) override; void RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) override; void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) override; - bool CheckMediaAccessPermission(content::WebContents *web_contents, const GURL& security_origin, content::MediaStreamType type) override; + bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host, const GURL& security_origin, content::MediaStreamType type) override; void RegisterProtocolHandler(content::WebContents* web_contents, const std::string& protocol, const GURL& url, bool user_gesture) override; void UnregisterProtocolHandler(content::WebContents* web_contents, const std::string& protocol, const GURL& url, bool user_gesture) override; // WebContentsObserver overrides void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; + void RenderViewHostChanged(content::RenderViewHost *old_host, content::RenderViewHost *new_host) override; void DidStartNavigation(content::NavigationHandle *navigation_handle) override; void DidFinishNavigation(content::NavigationHandle *navigation_handle) override; void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) override; void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override; void BeforeUnloadFired(const base::TimeTicks& proceed_time) override; void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) override; - void WasShown() override; + void OnVisibilityChanged(content::Visibility visibility) override; void DidFirstVisuallyNonEmptyPaint() override; void ActivateContents(content::WebContents* contents) override; void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription); void overrideWebPreferences(content::WebContents *, content::WebPreferences*); - void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ; + void allowCertificateError(const QSharedPointer<CertificateErrorController> &); + void selectClientCert(const QSharedPointer<ClientCertSelectController> &); void requestGeolocationPermission(const QUrl &requestingOrigin); void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FaviconManager *faviconManager(); @@ -152,11 +154,13 @@ public: WebEngineSettings *webEngineSettings() const; WebContentsAdapter *webContentsAdapter() const; + WebContentsAdapterClient *adapterClient() const { return m_viewClient; } private: - QWeakPointer<WebContentsAdapter> createWindow(content::WebContents *new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture); + QWeakPointer<WebContentsAdapter> createWindow(std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture); void EmitLoadStarted(const QUrl &url, bool isErrorPage = false); void EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString()); + void EmitLoadCommitted(); WebContentsAdapterClient *m_viewClient; QString m_lastSearchedString; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 6b68a9569..3c4465ae3 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -39,15 +39,18 @@ #include "web_contents_view_qt.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "content_browser_client_qt.h" #include "render_widget_host_view_qt_delegate.h" +#include "render_widget_host_view_qt.h" #include "type_conversion.h" #include "web_contents_adapter.h" #include "web_engine_context.h" -#include "components/spellcheck/spellcheck_build_features.h" +#include "components/spellcheck/spellcheck_buildflags.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/common/context_menu_params.h" #include <ui/gfx/image/image_skia.h> @@ -75,8 +78,6 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(conten view->setDelegate(m_factoryClient->CreateRenderWidgetHostViewQtDelegate(view)); if (m_client) view->setAdapterClient(m_client); - // Tell the RWHV delegate to attach itself to the native view container. - view->InitAsChild(0); return view; } @@ -92,17 +93,6 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForPopupWidget(c return view; } -void WebContentsViewQt::RenderViewCreated(content::RenderViewHost* host) -{ - // The render process is done creating the RenderView and it's ready to be routed - // messages at this point. - if (m_client && m_webContents) { - content::RenderWidgetHostView* rwhv = m_webContents->GetRenderWidgetHostView(); - if (rwhv) - rwhv->SetBackgroundColor(toSk(m_client->backgroundColor())); - } -} - void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context) { // This is passed through content::WebContents::CreateParams::context either as the native view's client @@ -184,7 +174,7 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara ret.setEditFlags((WebEngineContextMenuData::EditFlags)params.edit_flags); ret.setSuggestedFileName(toQt(params.suggested_filename.data())); ret.setIsEditable(params.is_editable); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) ret.setMisspelledWord(toQt(params.misspelled_word)); ret.setSpellCheckerSuggestions(fromVector(params.dictionary_suggestions)); #endif @@ -197,7 +187,7 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams ¶ms) { WebEngineContextMenuData contextMenuData(fromParams(params)); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) // Do not use params.spellcheck_enabled, since it is never // correctly initialized for chrome asynchronous spellchecking. // Even fixing the initialization in ContextMenuClientImpl::showContextMenu @@ -205,7 +195,7 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten // must be initialized to true due to the way how the initialization sequence // in SpellCheck works ie. typing the first word triggers the creation // of the SpellcheckService. Use user preference store instead. - contextMenuData.setIsSpellCheckerEnabled(m_client->browserContextAdapter()->isSpellCheckEnabled()); + contextMenuData.setIsSpellCheckerEnabled(m_client->profileAdapter()->isSpellCheckEnabled()); #endif m_client->contextMenuRequested(contextMenuData); } @@ -262,12 +252,6 @@ void WebContentsViewQt::TakeFocus(bool reverse) m_client->passOnFocus(reverse); } -void WebContentsViewQt::GetScreenInfo(content::ScreenInfo* results) const -{ - if (auto rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) - rwhv->GetScreenInfo(results); -} - void WebContentsViewQt::FocusThroughTabTraversal(bool reverse) { content::WebContentsImpl *web_contents = static_cast<content::WebContentsImpl*>(m_webContents); diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 1e4b27535..d1a2ff81e 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -41,18 +41,16 @@ #define WEB_CONTENTS_VIEW_QT_H #include "content/browser/renderer_host/render_view_host_delegate_view.h" -#include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host.h" -#include "qtwebenginecoreglobal_p.h" -#include "render_widget_host_view_qt.h" -#include "web_contents_adapter_client.h" -#include "web_contents_delegate_qt.h" -#include "web_engine_context.h" +#include "api/qtwebenginecoreglobal_p.h" + +namespace content { +class WebContents; +} namespace QtWebEngineCore { +class WebContentsAdapterClient; class WebContentsViewQt : public content::WebContentsView @@ -63,8 +61,8 @@ public: WebContentsViewQt(content::WebContents* webContents) : m_webContents(webContents) - , m_client(0) - , m_factoryClient(0) + , m_client(nullptr) + , m_factoryClient(nullptr) , m_allowOtherViews(false) { } @@ -79,9 +77,11 @@ public: void SetPageTitle(const base::string16& title) override { } - void RenderViewCreated(content::RenderViewHost* host) override; + void RenderViewCreated(content::RenderViewHost* host) override { } + + void RenderViewReady() override { } - void RenderViewSwappedIn(content::RenderViewHost* host) override { QT_NOT_YET_IMPLEMENTED } + void RenderViewHostChanged(content::RenderViewHost*, content::RenderViewHost*) override { } void SetOverscrollControllerEnabled(bool enabled) override { QT_NOT_YET_IMPLEMENTED } @@ -103,7 +103,7 @@ public: void RestoreFocus() override { QT_NOT_USED } - content::DropData* GetDropData() const override { QT_NOT_YET_IMPLEMENTED return 0; } + content::DropData* GetDropData() const override { QT_NOT_YET_IMPLEMENTED return nullptr; } gfx::Rect GetViewBounds() const override { QT_NOT_YET_IMPLEMENTED return gfx::Rect(); } @@ -118,8 +118,6 @@ public: void TakeFocus(bool reverse) override; - void GetScreenInfo(content::ScreenInfo* results) const override; - void FocusThroughTabTraversal(bool reverse) override; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 48e5bc438..fefccae0e 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -48,15 +48,15 @@ #include "base/run_loop.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) #include "chrome/browser/printing/print_job_manager.h" -#endif // defined(ENABLE_BASIC_PRINTING) +#endif #include "components/viz/common/features.h" #include "components/web_cache/browser/web_cache_manager.h" #include "content/browser/devtools/devtools_http_handler.h" #include "content/browser/gpu/gpu_main_thread_factory.h" #include "content/browser/renderer_host/render_process_host_impl.h" -#include "content/browser/utility_process_host_impl.h" +#include "content/browser/utility_process_host.h" #include "content/gpu/in_process_gpu_thread.h" #include "content/public/app/content_main.h" #include "content/public/app/content_main_runner.h" @@ -72,9 +72,11 @@ #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/ipc/host/gpu_switches.h" #include "media/audio/audio_manager.h" +#include "mojo/core/embedder/embedder.h" #include "net/base/port_util.h" -#include "ppapi/features/features.h" +#include "ppapi/buildflags/buildflags.h" #include "services/service_manager/sandbox/switches.h" +#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" #include "ui/events/event_switches.h" #include "ui/native_theme/native_theme_features.h" #include "ui/gl/gl_switches.h" @@ -83,16 +85,16 @@ #include "content/public/app/sandbox_helper_win.h" #endif // OS_WIN -#include "browser_context_adapter.h" +#include "api/qwebengineurlscheme.h" +#include "profile_adapter.h" #include "content_browser_client_qt.h" #include "content_client_qt.h" #include "content_main_delegate_qt.h" #include "devtools_manager_delegate_qt.h" -#include "gl_context_qt.h" #include "media_capture_devices_dispatcher.h" #include "net/webui_controller_factory_qt.h" #include "type_conversion.h" -#include "ozone/surface_factory_qt.h" +#include "ozone/gl_context_qt.h" #include "web_engine_library_info.h" #include <QFileInfo> @@ -117,23 +119,6 @@ QT_END_NAMESPACE namespace { -scoped_refptr<QtWebEngineCore::WebEngineContext> sContext; -static bool s_destroyed = false; - -void destroyContext() -{ - // Destroy WebEngineContext before its static pointer is zeroed and destructor called. - // Before destroying MessageLoop via destroying BrowserMainRunner destructor - // WebEngineContext's pointer is used. - sContext->destroy(); -#if !defined(NDEBUG) - if (!sContext->HasOneRef()) - qWarning("WebEngineContext leaked on exit, likely due to leaked WebEngine View or Page"); -#endif - sContext = nullptr; - s_destroyed = true; -} - #ifndef QT_NO_OPENGL bool usingANGLE() { @@ -157,10 +142,8 @@ bool usingQtQuick2DRenderer() } } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) if (device.isEmpty()) device = QQuickWindow::sceneGraphBackend(); -#endif if (device.isEmpty()) device = QString::fromLocal8Bit(qgetenv("QT_QUICK_BACKEND")); if (device.isEmpty()) @@ -172,7 +155,7 @@ bool usingQtQuick2DRenderer() return device != QLatin1String("default"); } #endif //QT_NO_OPENGL -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) { } @@ -197,9 +180,34 @@ bool usingSoftwareDynamicGL() #endif } +scoped_refptr<QtWebEngineCore::WebEngineContext> WebEngineContext::m_handle; +bool WebEngineContext::m_destroyed = false; + void WebEngineContext::destroyBrowserContext() { - m_defaultBrowserContext.reset(); + if (m_defaultProfileAdapter) + qWarning("PostMainMessageLoopRun is done, but global profile still exists !"); +} + +void WebEngineContext::addBrowserContext(ProfileAdapter *profileAdapter) +{ + Q_ASSERT(!m_profileAdapters.contains(profileAdapter)); + const QString path = profileAdapter->dataPath(); + if (!path.isEmpty()) { + for (auto profileAdapter : m_profileAdapters) { + if (profileAdapter->dataPath() == path) { + // QTBUG-66068 + qWarning("Using the same data path for profile, may corrupt the data."); + break; + } + } + } + m_profileAdapters.append(profileAdapter); +} + +void WebEngineContext::removeBrowserContext(ProfileAdapter *profileAdapter) +{ + m_profileAdapters.removeAll(profileAdapter); } void WebEngineContext::destroy() @@ -211,11 +219,17 @@ void WebEngineContext::destroy() // Flush the UI message loop before quitting. while (delegate->DoWork()) { } - if (m_defaultBrowserContext) - m_defaultBrowserContext->shutdown(); +#if QT_CONFIG(webengine_printing_and_pdf) + // Kill print job manager early as it has a content::NotificationRegistrar + m_printJobManager.reset(); +#endif + // Delete the global object and thus custom profiles - delete m_globalQObject; - m_globalQObject = nullptr; + m_defaultProfileAdapter.reset(); + m_globalQObject.reset(); + while (m_profileAdapters.count()) + delete m_profileAdapters.first(); + // Handle any events posted by browser-context shutdown. while (delegate->DoWork()) { } @@ -223,13 +237,17 @@ void WebEngineContext::destroy() m_devtoolsServer.reset(); m_runLoop->AfterRun(); - // Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner. + // Fixme: Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner. // RenderProcessHostImpl should be destroyed before WebEngineContext since // default BrowserContext might be used by the RenderprocessHostImpl's destructor. m_browserRunner.reset(); + // Destroying content-runner will force Chromium at_exit calls to run, and + // reap child processes. + m_contentRunner.reset(); + // Drop the false reference. - sContext->Release(); + m_handle->Release(); } WebEngineContext::~WebEngineContext() @@ -238,32 +256,53 @@ WebEngineContext::~WebEngineContext() Q_ASSERT(!m_globalQObject); Q_ASSERT(!m_devtoolsServer); Q_ASSERT(!m_browserRunner); + Q_ASSERT(m_profileAdapters.isEmpty()); } WebEngineContext *WebEngineContext::current() { - if (s_destroyed) + if (m_destroyed) return nullptr; - if (!sContext.get()) { - sContext = new WebEngineContext(); + if (!m_handle.get()) { + m_handle = new WebEngineContext(); // Make sure that we ramp down Chromium before QApplication destroys its X connection, etc. - qAddPostRoutine(destroyContext); - // Add a false reference so there is no race between unreferencing sContext and a global QApplication. - sContext->AddRef(); + qAddPostRoutine(WebEngineContext::destroyContextPostRoutine); + // Add a false reference so there is no race between unreferencing m_handle and a global QApplication. + m_handle->AddRef(); } - return sContext.get(); + return m_handle.get(); +} + +ProfileAdapter *WebEngineContext::createDefaultProfileAdapter() +{ + Q_ASSERT(!m_destroyed); + if (!m_defaultProfileAdapter) + m_defaultProfileAdapter.reset(new ProfileAdapter(QStringLiteral("Default"))); + return m_defaultProfileAdapter.get(); } -QSharedPointer<BrowserContextAdapter> WebEngineContext::defaultBrowserContext() +ProfileAdapter *WebEngineContext::defaultProfileAdapter() { - if (!m_defaultBrowserContext) - m_defaultBrowserContext = QSharedPointer<BrowserContextAdapter>::create(QStringLiteral("Default")); - return m_defaultBrowserContext; + return m_defaultProfileAdapter.get(); } QObject *WebEngineContext::globalQObject() { - return m_globalQObject; + return m_globalQObject.get(); +} + +void WebEngineContext::destroyContextPostRoutine() +{ + // Destroy WebEngineContext before its static pointer is zeroed and destructor called. + // Before destroying MessageLoop via destroying BrowserMainRunner destructor + // WebEngineContext's pointer is used. + m_handle->destroy(); +#if !defined(NDEBUG) + if (!m_handle->HasOneRef()) + qWarning("WebEngineContext leaked on exit, likely due to leaked WebEngine View or Page"); +#endif + m_handle = nullptr; + m_destroyed = true; } #ifndef CHROMIUM_VERSION @@ -287,24 +326,23 @@ static void appendToFeatureSwitch(base::CommandLine *commandLine, const char *fe WebEngineContext::WebEngineContext() : m_mainDelegate(new ContentMainDelegateQt) - , m_contentRunner(content::ContentMainRunner::Create()) - , m_browserRunner(content::BrowserMainRunner::Create()) , m_globalQObject(new QObject()) { -#if defined(USE_X11) - QString platform = qApp->platformName(); - if (platform != QLatin1String("xcb")) { - qWarning("WebEngine compiled with X11 support, however qpa backend is not xcb. " - "This may fail."); - } -#endif - + base::TaskScheduler::Create("Browser"); + m_contentRunner.reset(content::ContentMainRunner::Create()); + m_browserRunner.reset(content::BrowserMainRunner::Create()); #ifdef Q_OS_LINUX // Call qputenv before BrowserMainRunnerImpl::Initialize is called. // http://crbug.com/245466 qputenv("force_s3tc_enable", "true"); #endif + QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc")); + qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme + | QWebEngineUrlScheme::LocalAccessAllowed + | QWebEngineUrlScheme::ViewSourceAllowed); + QWebEngineUrlScheme::registerScheme(qrcScheme); + // Allow us to inject javascript like any webview toolkit. content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView(); @@ -344,12 +382,12 @@ WebEngineContext::WebEngineContext() bool disable_sandbox = qEnvironmentVariableIsSet(kDisableSandboxEnv); if (!disable_sandbox) { #if defined(Q_OS_WIN) - parsedCommandLine->AppendSwitch(switches::kNoSandbox); + parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); #elif defined(Q_OS_LINUX) parsedCommandLine->AppendSwitch(service_manager::switches::kDisableSetuidSandbox); #endif } else { - parsedCommandLine->AppendSwitch(switches::kNoSandbox); + parsedCommandLine->AppendSwitch(service_manager::switches::kNoSandbox); qInfo() << "Sandboxing disabled by user."; } @@ -361,9 +399,6 @@ WebEngineContext::WebEngineContext() // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X. parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); - // The Mojo local-storage is currently pretty broken and saves in $$PWD/Local\ Storage - parsedCommandLine->AppendSwitch(switches::kDisableMojoLocalStorage); - #if defined(Q_OS_MACOS) // Accelerated decoding currently does not work on macOS due to issues with OpenGL Rectangle // texture support. See QTBUG-60002. @@ -372,6 +407,8 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium); // Same problem with select popups. parsedCommandLine->AppendSwitch(switches::kDisableNativeGpuMemoryBuffers); + // SandboxV2 doesn't currently work for us + appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kMacV2Sandbox.name); #endif #if defined(Q_OS_WIN) @@ -391,18 +428,16 @@ WebEngineContext::WebEngineContext() appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); // Surface synchronization breaks our current graphics integration (since 65) appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kEnableSurfaceSynchronization.name); - // Scroll latching expects phases on all wheel events when it really only makes sense for simulated ones. - appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kTouchpadAndWheelScrollLatching.name); + // The video-capture service is not functioning at this moment (since 69) + appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kMojoVideoCapture.name); if (useEmbeddedSwitches) { + // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, features::kOverlayScrollbar.name); if (!parsedCommandLine->HasSwitch(switches::kDisablePinch)) parsedCommandLine->AppendSwitch(switches::kEnablePinch); parsedCommandLine->AppendSwitch(switches::kEnableViewport); parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); - parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); - parsedCommandLine->AppendSwitch(switches::kDisableGpuShaderDiskCache); - parsedCommandLine->AppendSwitch(switches::kDisable2dCanvasAntialiasing); parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } base::FeatureList::InitializeInstance( @@ -431,9 +466,6 @@ WebEngineContext::WebEngineContext() // If the native handle is QEGLNativeContext try to use GL ES/2, if there is no native handle // assume we are using wayland and try GL ES/2, and finally Ozone demands GL ES/2 too. if (qt_gl_global_share_context()->nativeHandle().isNull() -#ifdef USE_OZONE - || true -#endif || !strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext")) { if (qt_gl_global_share_context()->isOpenGLES()) { @@ -442,7 +474,7 @@ WebEngineContext::WebEngineContext() QOpenGLContext context; QSurfaceFormat format; - format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setRenderableType(QSurfaceFormat::OpenGL); format.setVersion(2, 0); context.setFormat(format); @@ -502,11 +534,11 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - content::UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); + content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); - mojo::edk::Init(); + mojo::core::Init(); content::ContentMainParams contentMainParams(m_mainDelegate.get()); #if defined(OS_WIN) @@ -542,7 +574,7 @@ WebEngineContext::WebEngineContext() media::AudioManager::SetGlobalAppName(QCoreApplication::applicationName().toStdString()); #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if QT_CONFIG(webengine_pepper_plugins) // Creating pepper plugins from the page (which calls PluginService::GetPluginInfoArray) // might fail unless the page queried the list of available plugins at least once // (which ends up calling PluginService::GetPlugins). Since the plugins list can only @@ -552,17 +584,17 @@ WebEngineContext::WebEngineContext() content::PluginService::GetInstance()->GetPlugins(base::Bind(&dummyGetPluginCallback)); #endif -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) m_printJobManager.reset(new printing::PrintJobManager()); -#endif // defined(ENABLE_BASIC_PRINTING) +#endif content::WebUIControllerFactory::RegisterFactory(WebUIControllerFactoryQt::GetInstance()); } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) printing::PrintJobManager* WebEngineContext::getPrintJobManager() { return m_printJobManager.get(); } -#endif // defined(ENABLE_BASIC_PRINTING) +#endif } // namespace diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index c1640bdf2..ce71984d4 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -40,15 +40,10 @@ #ifndef WEB_ENGINE_CONTEXT_H #define WEB_ENGINE_CONTEXT_H -#include "qtwebenginecoreglobal.h" - -#include "build/build_config.h" - +#include "build_config_qt.h" #include "base/memory/ref_counted.h" #include "base/values.h" -#include "printing/features/features.h" - -#include <QSharedPointer> +#include <QVector> namespace base { class RunLoop; @@ -59,38 +54,42 @@ class BrowserMainRunner; class ContentMainRunner; } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) namespace printing { class PrintJobManager; } -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif QT_FORWARD_DECLARE_CLASS(QObject) namespace QtWebEngineCore { -class BrowserContextAdapter; +class ProfileAdapter; class ContentMainDelegateQt; class DevToolsServerQt; -class SurfaceFactoryQt; bool usingSoftwareDynamicGL(); class WebEngineContext : public base::RefCounted<WebEngineContext> { public: static WebEngineContext *current(); + static void destroyContextPostRoutine(); + + ProfileAdapter *createDefaultProfileAdapter(); + ProfileAdapter *defaultProfileAdapter(); - QSharedPointer<BrowserContextAdapter> defaultBrowserContext(); QObject *globalQObject(); -#if BUILDFLAG(ENABLE_BASIC_PRINTING) +#if QT_CONFIG(webengine_printing_and_pdf) printing::PrintJobManager* getPrintJobManager(); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif void destroyBrowserContext(); + void addBrowserContext(ProfileAdapter *profileAdapter); + void removeBrowserContext(ProfileAdapter *profileAdapter); void destroy(); private: friend class base::RefCounted<WebEngineContext>; - friend class BrowserContextAdapter; + friend class ProfileAdapter; WebEngineContext(); ~WebEngineContext(); @@ -98,12 +97,16 @@ private: std::unique_ptr<ContentMainDelegateQt> m_mainDelegate; std::unique_ptr<content::ContentMainRunner> m_contentRunner; std::unique_ptr<content::BrowserMainRunner> m_browserRunner; - QObject* m_globalQObject; - QSharedPointer<BrowserContextAdapter> m_defaultBrowserContext; + std::unique_ptr<QObject> m_globalQObject; + std::unique_ptr<ProfileAdapter> m_defaultProfileAdapter; std::unique_ptr<DevToolsServerQt> m_devtoolsServer; -#if BUILDFLAG(ENABLE_BASIC_PRINTING) + QVector<ProfileAdapter*> m_profileAdapters; + +#if QT_CONFIG(webengine_printing_and_pdf) std::unique_ptr<printing::PrintJobManager> m_printJobManager; -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) +#endif + static scoped_refptr<QtWebEngineCore::WebEngineContext> m_handle; + static bool m_destroyed; }; } // namespace diff --git a/src/core/web_engine_error.h b/src/core/web_engine_error.h index 793d9d615..20af6d31f 100644 --- a/src/core/web_engine_error.h +++ b/src/core/web_engine_error.h @@ -37,12 +37,23 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef WEB_ENGINE_ERROR_H #define WEB_ENGINE_ERROR_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" -class QWEBENGINE_EXPORT WebEngineError +class QWEBENGINECORE_PRIVATE_EXPORT WebEngineError { public: diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index 515f763d2..3899ced25 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -43,7 +43,7 @@ #include "base/base_paths.h" #include "base/command_line.h" #include "base/files/file_util.h" -#include "components/spellcheck/spellcheck_build_features.h" +#include "components/spellcheck/spellcheck_buildflags.h" #include "content/public/common/content_paths.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" @@ -168,7 +168,7 @@ QString subProcessPath() % QLatin1Char('/') % processBinary; } - Q_FOREACH (const QString &candidate, candidatePaths) { + for (const QString &candidate : qAsConst(candidatePaths)) { if (QFileInfo::exists(candidate)) { processPath = candidate; break; @@ -208,7 +208,7 @@ QString localesPath() return potentialLocalesPath; } -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) QString dictionariesPath() { static QString potentialDictionariesPath; @@ -244,7 +244,7 @@ QString dictionariesPath() candidatePaths << libraryDictionariesPath; } - Q_FOREACH (const QString &candidate, candidatePaths) { + for (const QString &candidate : qAsConst(candidatePaths)) { if (QFileInfo::exists(candidate)) { potentialDictionariesPath = candidate; break; @@ -254,7 +254,7 @@ QString dictionariesPath() return potentialDictionariesPath; } -#endif // ENABLE_SPELLCHECK +#endif // QT_CONFIG(webengine_spellchecker) QString icuDataPath() { @@ -343,7 +343,7 @@ base::FilePath WebEngineLibraryInfo::getPath(int key) return toFilePath(icuDataPath()); case ui::DIR_LOCALES: return toFilePath(localesPath()); -#if BUILDFLAG(ENABLE_SPELLCHECK) +#if QT_CONFIG(webengine_spellchecker) case base::DIR_APP_DICTIONARIES: return toFilePath(dictionariesPath()); #endif diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 4cd4b6452..2e48a806a 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -126,7 +126,7 @@ WebEngineSettings::~WebEngineSettings() if (parentSettings) parentSettings->childSettings.remove(this); // In QML the profile and its settings may be garbage collected before the page and its settings. - Q_FOREACH (WebEngineSettings *settings, childSettings) { + for (WebEngineSettings *settings : qAsConst(childSettings)) { settings->parentSettings = 0; } } @@ -262,7 +262,7 @@ void WebEngineSettings::initDefaults() s_defaultAttributes.insert(LinksIncludedInFocusChain, true); s_defaultAttributes.insert(LocalStorageEnabled, true); s_defaultAttributes.insert(LocalContentCanAccessRemoteUrls, false); - s_defaultAttributes.insert(XSSAuditingEnabled, false); + s_defaultAttributes.insert(XSSAuditingEnabled, true); s_defaultAttributes.insert(SpatialNavigationEnabled, false); s_defaultAttributes.insert(LocalContentCanAccessFileUrls, true); s_defaultAttributes.insert(HyperlinkAuditingEnabled, false); @@ -298,6 +298,7 @@ void WebEngineSettings::initDefaults() s_defaultAttributes.insert(PlaybackRequiresUserGesture, playbackRequiresUserGesture); s_defaultAttributes.insert(WebRTCPublicInterfacesOnly, false); s_defaultAttributes.insert(JavascriptCanPaste, false); + s_defaultAttributes.insert(DnsPrefetchEnabled, false); } if (s_defaultFontFamilies.isEmpty()) { @@ -390,6 +391,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p : content::AutoplayPolicy::kNoUserGestureRequired; } prefs->dom_paste_enabled = testAttribute(JavascriptCanPaste); + prefs->dns_prefetching_enabled = testAttribute(DnsPrefetchEnabled); // Fonts settings. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); @@ -409,7 +411,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p bool WebEngineSettings::applySettingsToRendererPreferences(content::RendererPreferences *prefs) { bool changed = false; -#if BUILDFLAG(ENABLE_WEBRTC) +#if QT_CONFIG(webengine_webrtc) if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) { std::string webrtc_ip_handling_policy = testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly @@ -426,7 +428,7 @@ bool WebEngineSettings::applySettingsToRendererPreferences(content::RendererPref void WebEngineSettings::scheduleApplyRecursively() { scheduleApply(); - Q_FOREACH (WebEngineSettings *settings, childSettings) { + for (WebEngineSettings *settings : qAsConst(childSettings)) { settings->scheduleApply(); } } diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index eba9bf7ea..06a7a6004 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -37,10 +37,21 @@ ** ****************************************************************************/ +// +// 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. +// + #ifndef WEB_ENGINE_SETTINGS_H #define WEB_ENGINE_SETTINGS_H -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include <QScopedPointer> #include <QHash> @@ -57,7 +68,7 @@ namespace QtWebEngineCore { class BatchTimer; class WebContentsAdapter; -class QWEBENGINE_EXPORT WebEngineSettings { +class QWEBENGINECORE_PRIVATE_EXPORT WebEngineSettings { public: // Attributes. Names match the ones from the public widgets API. enum Attribute { @@ -91,6 +102,7 @@ public: PlaybackRequiresUserGesture, WebRTCPublicInterfacesOnly, JavascriptCanPaste, + DnsPrefetchEnabled, }; // Must match the values from the public API in qwebenginesettings.h. diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 792c4c612..04d4930ec 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -65,10 +65,13 @@ */ #include "web_event_factory.h" -#include "third_party/WebKit/Source/platform/WindowsKeyboardCodes.h" +#include "third_party/blink/renderer/platform/windows_keyboard_codes.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" + +#include <QtGui/private/qtgui-config_p.h> #include <QCoreApplication> #include <QElapsedTimer> @@ -83,11 +86,134 @@ using namespace blink; -static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) +enum class KeyboardDriver { Unknown, Windows, Cocoa, Xkb, Evdev }; + +static KeyboardDriver keyboardDriverImpl() +{ + QString platformName = QGuiApplication::platformName(); + + if (platformName == QLatin1Literal("windows")) + return KeyboardDriver::Windows; + + if (platformName == QLatin1Literal("cocoa")) + return KeyboardDriver::Cocoa; + + if (platformName == QLatin1Literal("xcb") || platformName == QLatin1Literal("wayland")) + return KeyboardDriver::Xkb; + +#if QT_CONFIG(libinput) && QT_CONFIG(xkbcommon_evdev) + // Based on QEglFSIntegration::createInputHandlers and QLibInputKeyboard::processKey. + if (platformName == QLatin1Literal("eglfs") && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) + return KeyboardDriver::Xkb; +#endif + +#if QT_CONFIG(evdev) + // Based on QEglFSIntegration::createInputHandlers. + if (platformName == QLatin1Literal("eglfs")) + return KeyboardDriver::Evdev; +#endif + + return KeyboardDriver::Unknown; +} + +static KeyboardDriver keyboardDriver() +{ + static KeyboardDriver cached = keyboardDriverImpl(); + return cached; +} + +// Qt swaps the Control and Meta keys on macOS (unless the attribute +// AA_MacDontSwapCtrlAndMeta is set). To preserve compatibility with Chromium we +// want to unswap them when forwarding events. The following two functions, +// qtKeyForKeyEvent and qtModifiersForEvent, should be used for accessing the +// key() and modifiers() properties to ensure that the unswapping is done +// consistently. +static int qtKeyForKeyEvent(const QKeyEvent *ev) +{ + int key = ev->key(); + if (keyboardDriver() == KeyboardDriver::Cocoa && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + if (key == Qt::Key_Control) + return Qt::Key_Meta; + if (key == Qt::Key_Meta) + return Qt::Key_Control; + } + return key; +} + +// See above +static Qt::KeyboardModifiers qtModifiersForEvent(const QInputEvent *ev) +{ + Qt::KeyboardModifiers modifiers = ev->modifiers(); + if (keyboardDriver() == KeyboardDriver::Cocoa && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + bool controlModifier = modifiers.testFlag(Qt::ControlModifier); + bool metaModifier = modifiers.testFlag(Qt::MetaModifier); + modifiers.setFlag(Qt::ControlModifier, metaModifier); + modifiers.setFlag(Qt::MetaModifier, controlModifier); + } + return modifiers; +} + +// QKeyEvent::text() has some limits that we need to work around. +// +// On Linux, the Control modifier transformation is applied [1]. For example, +// pressing Ctrl+@ generates the text "\u0000". We would like "@" instead. +// +// [1]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier +// +// On macOS, if the Control modifier is used, then no text is generated at all. +// We need some text. +// +// The workaround is to use QKeyEvent::key() instead, when needed. Contrary to +// the documentation, QKeyEvent::key() is not at all limited to the values +// listed in the Qt::Key enum: it can actually contain any Unicode codepoint. +// The only drawback is that letters are always upper cased. +static QString qtTextForKeyEvent(const QKeyEvent *ev, int qtKey, Qt::KeyboardModifiers qtModifiers) +{ + QString text = ev->text(); + + if ((qtModifiers & Qt::ControlModifier) && keyboardDriver() == KeyboardDriver::Xkb) + text.clear(); + + if (!text.isEmpty() || qtKey >= Qt::Key_Escape) + return text; + + QChar ch(qtKey); + if (!(qtModifiers & Qt::ShiftModifier)) // No way to check for caps lock + ch = ch.toLower(); + + text.append(ch); + return text; +} + +// The 'native key code' in Chromium refers to +// +// - On Windows: the Windows OEM scancode. +// - On macOS: the NSEvent's keyCode. +// - On Linux: The XKB keycode. +static quint32 nativeKeyCodeForKeyEvent(const QKeyEvent *ev) +{ + // Ifdefs here should match <ui/events/keycodes/dom/keycode_converter.cc>, + // since that is where the native key code is eventually used. + // + // Note that Xkb key codes are only supported under Linux (no BSDs, + // Cygwin/X, etc). Also evdev key codes are *not* supported for the same + // reason. +#if defined(Q_OS_WINDOWS) + return keyboardDriver() == KeyboardDriver::Windows ? ev->nativeScanCode() : 0; +#elif defined(Q_OS_MACOS) + return keyboardDriver() == KeyboardDriver::Cocoa ? ev->nativeVirtualKey() : 0; +#elif defined(Q_OS_LINUX) + return keyboardDriver() == KeyboardDriver::Xkb ? ev->nativeScanCode() : 0; +#else + return 0; // 0 means unknown, KeyboardEvent.code will be empty string. +#endif +} + +static int windowsKeyCodeForQtKey(int qtKey, bool isKeypad) { // Determine wheter the event comes from the keypad if (isKeypad) { - switch (keycode) { + switch (qtKey) { case Qt::Key_0: return VK_NUMPAD0; // (60) Numeric keypad 0 key case Qt::Key_1: @@ -154,7 +280,7 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) } } else { - switch (keycode) { + switch (qtKey) { case Qt::Key_Backspace: return VK_BACK; // (08) BACKSPACE key case Qt::Key_Backtab: @@ -647,12 +773,10 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) * - ui::DomKey::VIDEO_MODE_NEXT * - ui::DomKey::WINK */ -static ui::DomKey getDomKeyFromQKeyEvent(QKeyEvent *ev) +static ui::DomKey domKeyForQtKey(int qtKey) { - if (!ev->text().isEmpty()) - return ui::DomKey::FromCharacter(ev->text().toUcs4().first()); - - switch (ev->key()) { + Q_ASSERT(qtKey >= Qt::Key_Escape); + switch (qtKey) { case Qt::Key_Backspace: return ui::DomKey::BACKSPACE; case Qt::Key_Tab: @@ -1022,20 +1146,17 @@ static ui::DomKey getDomKeyFromQKeyEvent(QKeyEvent *ev) } } -static inline double currentTimeForEvent(const QEvent *event) +static inline base::TimeTicks currentTimeForEvent(const QEvent *event) { Q_ASSERT(event); if (event->type() != QEvent::Leave) { const QInputEvent *inputEvent = static_cast<const QInputEvent *>(event); if (inputEvent->timestamp()) - return static_cast<double>(inputEvent->timestamp()) / 1000; + return base::TimeTicks::FromInternalValue(inputEvent->timestamp() * 1000); } - static QElapsedTimer timer; - if (!timer.isValid()) - timer.start(); - return static_cast<double>(timer.elapsed()) / 1000; + return base::TimeTicks::Now(); } template<class T> @@ -1085,17 +1206,10 @@ static inline WebInputEvent::Modifiers modifierForKeyCode(int key) return WebInputEvent::kShiftKey; case Qt::Key_Alt: return WebInputEvent::kAltKey; -#if defined(Q_OS_OSX) - case Qt::Key_Control: - return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::kMetaKey : WebInputEvent::kControlKey; - case Qt::Key_Meta: - return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::kControlKey : WebInputEvent::kMetaKey; -#else case Qt::Key_Control: return WebInputEvent::kControlKey; case Qt::Key_Meta: return WebInputEvent::kMetaKey; -#endif default: return static_cast<WebInputEvent::Modifiers>(0); } @@ -1104,22 +1218,11 @@ static inline WebInputEvent::Modifiers modifierForKeyCode(int key) static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* event) { unsigned result = 0; - Qt::KeyboardModifiers modifiers = event->modifiers(); -#if defined(Q_OS_OSX) - if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - if (modifiers & Qt::ControlModifier) - result |= WebInputEvent::kMetaKey; - if (modifiers & Qt::MetaModifier) - result |= WebInputEvent::kControlKey; - } else -#endif - { - if (modifiers & Qt::ControlModifier) - result |= WebInputEvent::kControlKey; - if (modifiers & Qt::MetaModifier) - result |= WebInputEvent::kMetaKey; - } - + Qt::KeyboardModifiers modifiers = qtModifiersForEvent(event); + if (modifiers & Qt::ControlModifier) + result |= WebInputEvent::kControlKey; + if (modifiers & Qt::MetaModifier) + result |= WebInputEvent::kMetaKey; if (modifiers & Qt::ShiftModifier) result |= WebInputEvent::kShiftKey; if (modifiers & Qt::AltModifier) @@ -1141,7 +1244,7 @@ static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* even const QKeyEvent *keyEvent = static_cast<const QKeyEvent*>(event); if (keyEvent->isAutoRepeat()) result |= WebInputEvent::kIsAutoRepeat; - result |= modifierForKeyCode(keyEvent->key()); + result |= modifierForKeyCode(qtKeyForKeyEvent(keyEvent)); } default: break; @@ -1222,7 +1325,7 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev, double dpiScale) { WebMouseEvent webKitEvent; - webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetTimeStamp(currentTimeForEvent(ev)); webKitEvent.SetModifiers(modifiersForEvent(ev)); webKitEvent.SetType(webEventTypeForEvent(ev)); @@ -1260,7 +1363,7 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QEvent *ev) Q_ASSERT(ev->type() == QEvent::Leave || ev->type() == QEvent::HoverLeave); WebMouseEvent webKitEvent; - webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetTimeStamp(currentTimeForEvent(ev)); webKitEvent.SetType(WebInputEvent::kMouseLeave); return webKitEvent; } @@ -1269,16 +1372,16 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QEvent *ev) WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, double dpiScale) { WebGestureEvent webKitEvent; - webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetTimeStamp(currentTimeForEvent(ev)); webKitEvent.SetModifiers(modifiersForEvent(ev)); - webKitEvent.x = static_cast<int>(ev->localPos().x() / dpiScale); - webKitEvent.y = static_cast<int>(ev->localPos().y() / dpiScale); + webKitEvent.SetPositionInWidget(WebFloatPoint(ev->localPos().x() / dpiScale, + ev->localPos().y() / dpiScale)); - webKitEvent.global_x = static_cast<int>(ev->screenPos().x() / dpiScale); - webKitEvent.global_y = static_cast<int>(ev->screenPos().y() / dpiScale); + webKitEvent.SetPositionInScreen(WebFloatPoint(ev->screenPos().x() / dpiScale, + ev->screenPos().y() / dpiScale)); - webKitEvent.source_device = blink::kWebGestureDeviceTouchpad; + webKitEvent.SetSourceDevice(blink::kWebGestureDeviceTouchpad); Qt::NativeGestureType gestureType = ev->gestureType(); switch (gestureType) { @@ -1310,22 +1413,21 @@ static void setBlinkWheelEventDelta(blink::WebMouseWheelEvent &webEvent) // a pixel delta based on ticks and scroll per line. static const float cDefaultQtScrollStep = 20.f; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) static const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines(); -#else - static const int wheelScrollLines = 3; -#endif webEvent.delta_x = webEvent.wheel_ticks_x * wheelScrollLines * cDefaultQtScrollStep; webEvent.delta_y = webEvent.wheel_ticks_y * wheelScrollLines * cDefaultQtScrollStep; } -blink::WebMouseWheelEvent::Phase toBlinkPhase(Qt::ScrollPhase phase) +blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev) { - switch (phase) { + switch (ev->phase()) { case Qt::NoScrollPhase: +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + case Qt::ScrollMomentum: +#endif return blink::WebMouseWheelEvent::kPhaseNone; case Qt::ScrollBegin: - return blink::WebMouseWheelEvent::kPhaseBegan; + return ev->angleDelta().isNull() ? blink::WebMouseWheelEvent::kPhaseMayBegin : blink::WebMouseWheelEvent::kPhaseBegan; case Qt::ScrollUpdate: return blink::WebMouseWheelEvent::kPhaseChanged; case Qt::ScrollEnd: @@ -1340,13 +1442,13 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, doub WebMouseWheelEvent webEvent; webEvent.SetType(webEventTypeForEvent(ev)); webEvent.SetModifiers(modifiersForEvent(ev)); - webEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webEvent.SetTimeStamp(currentTimeForEvent(ev)); webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale); webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; - webEvent.phase = toBlinkPhase(ev->phase()); + webEvent.phase = toBlinkPhase(ev); webEvent.has_precise_scrolling_deltas = true; setBlinkWheelEventDelta(webEvent); @@ -1359,10 +1461,10 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, return false; if (modifiersForEvent(ev) != webEvent.GetModifiers()) return false; - if (toBlinkPhase(ev->phase()) != webEvent.phase) + if (toBlinkPhase(ev) != webEvent.phase) return false; - webEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webEvent.SetTimeStamp(currentTimeForEvent(ev)); webEvent.SetPositionInWidget(ev->x() / dpiScale, ev->y() / dpiScale); webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); @@ -1376,23 +1478,40 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev)); - webKitEvent.SetTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.SetTimeStamp(currentTimeForEvent(ev)); webKitEvent.SetModifiers(modifiersForEvent(ev)); webKitEvent.SetType(webEventTypeForEvent(ev)); - webKitEvent.native_key_code = ev->nativeVirtualKey(); - webKitEvent.windows_key_code = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); - webKitEvent.dom_key = getDomKeyFromQKeyEvent(ev); - - ui::DomCode domCode = ui::DomCode::NONE; - int scanCode = ev->nativeScanCode(); - if (scanCode) - domCode = ui::KeycodeConverter::NativeKeycodeToDomCode(scanCode); - webKitEvent.dom_code = static_cast<int>(domCode); - - const ushort* text = ev->text().utf16(); - memcpy(&webKitEvent.text, text, std::min(sizeof(webKitEvent.text), size_t(ev->text().length() * 2))); - memcpy(&webKitEvent.unmodified_text, text, std::min(sizeof(webKitEvent.unmodified_text), size_t(ev->text().length() * 2))); + int qtKey = qtKeyForKeyEvent(ev); + Qt::KeyboardModifiers qtModifiers = qtModifiersForEvent(ev); + QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers); + + webKitEvent.native_key_code = nativeKeyCodeForKeyEvent(ev); + webKitEvent.windows_key_code = windowsKeyCodeForQtKey(qtKey, qtModifiers & Qt::KeypadModifier); + + if (qtKey >= Qt::Key_Escape) + webKitEvent.dom_key = domKeyForQtKey(qtKey); + else if (!qtText.isEmpty()) + webKitEvent.dom_key = ui::DomKey::FromCharacter(qtText.toUcs4().first()); + + // The dom_code field should contain the USB keycode of the *physical* key + // that was pressed. Physical meaning independent of layout and modifiers. + // + // Since this information is not available from QKeyEvent in portable form, + // we try to compute it from the native key code. If there's no native key + // code available either, then we assume a US layout and convert it from + // windows_key_code. The result will be incorrect on non-US layouts. + if (webKitEvent.native_key_code) + webKitEvent.dom_code = static_cast<int>( + ui::KeycodeConverter::NativeKeycodeToDomCode(webKitEvent.native_key_code)); + else + webKitEvent.dom_code = static_cast<int>( + ui::UsLayoutKeyboardCodeToDomCode(static_cast<ui::KeyboardCode>(webKitEvent.windows_key_code))); + + const ushort* text = qtText.utf16(); + size_t textSize = std::min(sizeof(webKitEvent.text), size_t(qtText.length() * 2)); + memcpy(&webKitEvent.text, text, textSize); + memcpy(&webKitEvent.unmodified_text, text, textSize); if (webKitEvent.windows_key_code == VK_RETURN) { // This is the same behavior as GTK: @@ -1471,10 +1590,7 @@ bool WebEventFactory::getEditCommand(QKeyEvent *event, std::string *editCommand) } #ifdef Q_OS_MACOS - Qt::KeyboardModifier cmdKey = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? - Qt::MetaModifier : - Qt::ControlModifier; - if ((event->modifiers() & ~Qt::ShiftModifier) == cmdKey) { + if ((qtModifiersForEvent(event) & ~Qt::ShiftModifier) == Qt::MetaModifier) { if (event->key() == Qt::Key_Backspace) { *editCommand = "DeleteToBeginningOfLine"; return true; diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index 81f940c4b..4b22de7d7 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -42,10 +42,10 @@ #include "content/public/browser/native_web_keyboard_event.h" #ifndef QT_NO_GESTURES -#include "third_party/WebKit/public/platform/WebGestureEvent.h" +#include "third_party/blink/public/platform/web_gesture_event.h" #endif -#include "third_party/WebKit/public/platform/WebMouseEvent.h" -#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h" +#include "third_party/blink/public/platform/web_mouse_event.h" +#include "third_party/blink/public/platform/web_mouse_wheel_event.h" #include <QtGlobal> |